blob: f8f7e652e26c0d63578a1e95abc34e895ea5a0c7 [file] [log] [blame]
/*
* 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;
import static android.Manifest.permission.ACCESS_WIFI_STATE;
import static android.Manifest.permission.MANAGE_WIFI_COUNTRY_CODE;
import static android.Manifest.permission.WIFI_ACCESS_COEX_UNSAFE_CHANNELS;
import static android.Manifest.permission.WIFI_UPDATE_COEX_UNSAFE_CHANNELS;
import static android.net.wifi.WifiAvailableChannel.FILTER_REGULATORY;
import static android.net.wifi.WifiAvailableChannel.OP_MODE_STA;
import static android.net.wifi.WifiConfiguration.METERED_OVERRIDE_METERED;
import static android.net.wifi.WifiManager.COEX_RESTRICTION_SOFTAP;
import static android.net.wifi.WifiManager.COEX_RESTRICTION_WIFI_AWARE;
import static android.net.wifi.WifiManager.COEX_RESTRICTION_WIFI_DIRECT;
import static android.net.wifi.WifiManager.DEVICE_MOBILITY_STATE_STATIONARY;
import static android.net.wifi.WifiManager.EASY_CONNECT_CRYPTOGRAPHY_CURVE_PRIME256V1;
import static android.net.wifi.WifiManager.IFACE_IP_MODE_CONFIGURATION_ERROR;
import static android.net.wifi.WifiManager.IFACE_IP_MODE_LOCAL_ONLY;
import static android.net.wifi.WifiManager.IFACE_IP_MODE_TETHERED;
import static android.net.wifi.WifiManager.LocalOnlyHotspotCallback.ERROR_GENERIC;
import static android.net.wifi.WifiManager.LocalOnlyHotspotCallback.ERROR_INCOMPATIBLE_MODE;
import static android.net.wifi.WifiManager.LocalOnlyHotspotCallback.ERROR_NO_CHANNEL;
import static android.net.wifi.WifiManager.LocalOnlyHotspotCallback.ERROR_TETHERING_DISALLOWED;
import static android.net.wifi.WifiManager.LocalOnlyHotspotCallback.REQUEST_REGISTERED;
import static android.net.wifi.WifiManager.SAP_START_FAILURE_GENERAL;
import static android.net.wifi.WifiManager.SAP_START_FAILURE_NO_CHANNEL;
import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLED;
import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLING;
import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLED;
import static android.net.wifi.WifiManager.WIFI_AP_STATE_FAILED;
import static android.net.wifi.WifiManager.WIFI_STATE_DISABLED;
import static android.net.wifi.WifiScanner.WIFI_BAND_24_GHZ;
import static android.net.wifi.WifiScanner.WIFI_BAND_5_GHZ;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
import static com.android.server.wifi.ActiveModeManager.ROLE_CLIENT_LOCAL_ONLY;
import static com.android.server.wifi.ActiveModeManager.ROLE_CLIENT_SECONDARY_LONG_LIVED;
import static com.android.server.wifi.LocalOnlyHotspotRequestInfo.HOTSPOT_NO_ERROR;
import static com.android.server.wifi.SelfRecovery.REASON_API_CALL;
import static com.android.server.wifi.WifiConfigurationTestUtil.SECURITY_NONE;
import static com.android.server.wifi.WifiSettingsConfigStore.WIFI_VERBOSE_LOGGING_ENABLED;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.junit.Assume.assumeTrue;
import static org.mockito.AdditionalAnswers.returnsSecondArg;
import static org.mockito.AdditionalMatchers.aryEq;
import static org.mockito.ArgumentMatchers.notNull;
import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.anyBoolean;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.argThat;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.ignoreStubs;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.isNull;
import static org.mockito.Mockito.lenient;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.validateMockitoUsage;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
import android.Manifest;
import android.app.ActivityManager;
import android.app.AppOpsManager;
import android.app.test.MockAnswerUtil.AnswerWithArguments;
import android.bluetooth.BluetoothAdapter;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.net.DhcpInfo;
import android.net.DhcpResultsParcelable;
import android.net.MacAddress;
import android.net.NetworkStack;
import android.net.Uri;
import android.net.wifi.CoexUnsafeChannel;
import android.net.wifi.IActionListener;
import android.net.wifi.ICoexCallback;
import android.net.wifi.IDppCallback;
import android.net.wifi.ILocalOnlyHotspotCallback;
import android.net.wifi.INetworkRequestMatchCallback;
import android.net.wifi.IOnWifiActivityEnergyInfoListener;
import android.net.wifi.IOnWifiUsabilityStatsListener;
import android.net.wifi.IScanResultsCallback;
import android.net.wifi.ISoftApCallback;
import android.net.wifi.ISubsystemRestartCallback;
import android.net.wifi.ISuggestionConnectionStatusListener;
import android.net.wifi.ISuggestionUserApprovalStatusListener;
import android.net.wifi.ITrafficStateCallback;
import android.net.wifi.IWifiConnectedNetworkScorer;
import android.net.wifi.IWifiVerboseLoggingStatusChangedListener;
import android.net.wifi.ScanResult;
import android.net.wifi.SecurityParams;
import android.net.wifi.SoftApConfiguration;
import android.net.wifi.SoftApInfo;
import android.net.wifi.WifiClient;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiConfiguration.KeyMgmt;
import android.net.wifi.WifiEnterpriseConfig;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiManager.LocalOnlyHotspotCallback;
import android.net.wifi.WifiNetworkSuggestion;
import android.net.wifi.WifiScanner;
import android.net.wifi.WifiSsid;
import android.net.wifi.hotspot2.IProvisioningCallback;
import android.net.wifi.hotspot2.OsuProvider;
import android.net.wifi.hotspot2.PasspointConfiguration;
import android.net.wifi.hotspot2.pps.Credential;
import android.net.wifi.hotspot2.pps.HomeSp;
import android.os.Binder;
import android.os.Build;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.IPowerManager;
import android.os.IThermalService;
import android.os.Parcel;
import android.os.PowerManager;
import android.os.Process;
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.WorkSource;
import android.os.connectivity.WifiActivityEnergyInfo;
import android.os.test.TestLooper;
import android.telephony.CarrierConfigManager;
import android.telephony.PhoneStateListener;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import androidx.test.filters.SmallTest;
import com.android.internal.os.PowerProfile;
import com.android.modules.utils.ParceledListSlice;
import com.android.modules.utils.build.SdkLevel;
import com.android.server.wifi.WifiServiceImpl.LocalOnlyRequestorCallback;
import com.android.server.wifi.WifiServiceImpl.SoftApCallbackInternal;
import com.android.server.wifi.coex.CoexManager;
import com.android.server.wifi.hotspot2.PasspointManager;
import com.android.server.wifi.hotspot2.PasspointProvisioningTestUtil;
import com.android.server.wifi.proto.nano.WifiMetricsProto.UserActionEvent;
import com.android.server.wifi.util.ActionListenerWrapper;
import com.android.server.wifi.util.ApConfigUtil;
import com.android.server.wifi.util.LastCallerInfoManager;
import com.android.server.wifi.util.WifiPermissionsUtil;
import com.android.server.wifi.util.WifiPermissionsWrapper;
import com.android.wifi.resources.R;
import com.google.common.base.Strings;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.ArgumentMatcher;
import org.mockito.Captor;
import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.MockitoSession;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Unit tests for {@link WifiServiceImpl}.
*
* Note: this is intended to build up over time and will not immediately cover the entire file.
*/
@SmallTest
public class WifiServiceImplTest extends WifiBaseTest {
private static final String TAG = "WifiServiceImplTest";
private static final String SCAN_PACKAGE_NAME = "scanPackage";
private static final int DEFAULT_VERBOSE_LOGGING = 0;
private static final String ANDROID_SYSTEM_PACKAGE = "android";
private static final String TEST_PACKAGE_NAME = "TestPackage";
private static final String TEST_PACKAGE_NAME_OTHER = "TestPackageOther";
private static final String TEST_FEATURE_ID = "TestFeature";
private static final String SYSUI_PACKAGE_NAME = "com.android.systemui";
private static final int TEST_PID = 6789;
private static final int TEST_PID2 = 9876;
private static final int TEST_UID = 1200000;
private static final int OTHER_TEST_UID = 1300000;
private static final int TEST_USER_HANDLE = 13;
private static final int TEST_WIFI_CONNECTED_NETWORK_SCORER_IDENTIFIER = 1;
private static final String WIFI_IFACE_NAME = "wlan0";
private static final String WIFI_IFACE_NAME2 = "wlan1";
private static final String TEST_COUNTRY_CODE = "US";
private static final String TEST_FACTORY_MAC = "10:22:34:56:78:92";
private static final MacAddress TEST_FACTORY_MAC_ADDR = MacAddress.fromString(TEST_FACTORY_MAC);
private static final String TEST_FQDN = "testfqdn";
private static final String TEST_FRIENDLY_NAME = "testfriendlyname";
private static final List<WifiConfiguration> TEST_WIFI_CONFIGURATION_LIST = Arrays.asList(
WifiConfigurationTestUtil.generateWifiConfig(
0, 1000000, "\"red\"", true, true, null, null,
SECURITY_NONE),
WifiConfigurationTestUtil.generateWifiConfig(
1, 1000001, "\"green\"", true, false, "example.com", "Green",
SECURITY_NONE),
WifiConfigurationTestUtil.generateWifiConfig(
2, 1200000, "\"blue\"", false, true, null, null,
SECURITY_NONE),
WifiConfigurationTestUtil.generateWifiConfig(
3, 1100000, "\"cyan\"", true, true, null, null,
SECURITY_NONE),
WifiConfigurationTestUtil.generateWifiConfig(
4, 1100001, "\"yellow\"", true, true, "example.org", "Yellow",
SECURITY_NONE),
WifiConfigurationTestUtil.generateWifiConfig(
5, 1100002, "\"magenta\"", false, false, null, null,
SECURITY_NONE));
private static final int TEST_AP_FREQUENCY = 2412;
private static final int TEST_AP_BANDWIDTH = SoftApInfo.CHANNEL_WIDTH_20MHZ;
private static final int NETWORK_CALLBACK_ID = 1100;
private static final String TEST_CAP = "[RSN-PSK-CCMP]";
private static final String TEST_SSID = "Sid's Place";
private static final String TEST_SSID_WITH_QUOTES = "\"" + TEST_SSID + "\"";
private static final String TEST_BSSID = "01:02:03:04:05:06";
private static final String TEST_PACKAGE = "package";
private static final int TEST_NETWORK_ID = 567;
private static final WorkSource TEST_SETTINGS_WORKSOURCE = new WorkSource();
private static final int TEST_SUB_ID = 1;
private SoftApInfo mTestSoftApInfo;
private List<SoftApInfo> mTestSoftApInfoList;
private Map<String, List<WifiClient>> mTestSoftApClients;
private Map<String, SoftApInfo> mTestSoftApInfos;
private WifiServiceImpl mWifiServiceImpl;
private TestLooper mLooper;
private WifiThreadRunner mWifiThreadRunner;
private PowerManager mPowerManager;
private PhoneStateListener mPhoneStateListener;
private int mPid;
private int mPid2 = Process.myPid();
private OsuProvider mOsuProvider;
private SoftApCallbackInternal mStateMachineSoftApCallback;
private SoftApCallbackInternal mLohsApCallback;
private String mLohsInterfaceName;
private ApplicationInfo mApplicationInfo;
private List<ClientModeManager> mClientModeManagers;
private static final String DPP_URI = "DPP:some_dpp_uri";
private static final String DPP_PRODUCT_INFO = "DPP:some_dpp_uri_info";
private final ArgumentCaptor<BroadcastReceiver> mBroadcastReceiverCaptor =
ArgumentCaptor.forClass(BroadcastReceiver.class);
final ArgumentCaptor<SoftApModeConfiguration> mSoftApModeConfigCaptor =
ArgumentCaptor.forClass(SoftApModeConfiguration.class);
@Mock Context mContext;
@Mock Context mContextAsUser;
@Mock WifiInjector mWifiInjector;
@Mock WifiCountryCode mWifiCountryCode;
@Mock Clock mClock;
@Mock WifiTrafficPoller mWifiTrafficPoller;
@Mock ConcreteClientModeManager mClientModeManager;
@Mock ActiveModeWarden mActiveModeWarden;
@Mock HandlerThread mHandlerThread;
@Mock Resources mResources;
@Mock FrameworkFacade mFrameworkFacade;
@Mock WifiLockManager mLockManager;
@Mock WifiMulticastLockManager mWifiMulticastLockManager;
@Mock WifiLastResortWatchdog mWifiLastResortWatchdog;
@Mock WifiBackupRestore mWifiBackupRestore;
@Mock SoftApBackupRestore mSoftApBackupRestore;
@Mock WifiMetrics mWifiMetrics;
@Mock WifiPermissionsUtil mWifiPermissionsUtil;
@Mock WifiPermissionsWrapper mWifiPermissionsWrapper;
@Mock WifiSettingsStore mSettingsStore;
@Mock ContentResolver mContentResolver;
@Mock PackageManager mPackageManager;
@Mock UserManager mUserManager;
@Mock WifiApConfigStore mWifiApConfigStore;
@Mock WifiConfiguration mApConfig;
@Mock ActivityManager mActivityManager;
@Mock AppOpsManager mAppOpsManager;
@Mock IBinder mAppBinder;
@Mock IBinder mAnotherAppBinder;
@Mock LocalOnlyHotspotRequestInfo mRequestInfo;
@Mock LocalOnlyHotspotRequestInfo mRequestInfo2;
@Mock IProvisioningCallback mProvisioningCallback;
@Mock ISoftApCallback mClientSoftApCallback;
@Mock ISoftApCallback mAnotherSoftApCallback;
@Mock PowerProfile mPowerProfile;
@Mock WifiTrafficPoller mWifiTrafficPolller;
@Mock ScanRequestProxy mScanRequestProxy;
@Mock WakeupController mWakeupController;
@Mock ITrafficStateCallback mTrafficStateCallback;
@Mock INetworkRequestMatchCallback mNetworkRequestMatchCallback;
@Mock WifiNetworkSuggestionsManager mWifiNetworkSuggestionsManager;
@Mock TelephonyManager mTelephonyManager;
@Mock CoexManager mCoexManager;
@Mock IOnWifiUsabilityStatsListener mOnWifiUsabilityStatsListener;
@Mock WifiConfigManager mWifiConfigManager;
@Mock WifiScoreCard mWifiScoreCard;
@Mock WifiHealthMonitor mWifiHealthMonitor;
@Mock PasspointManager mPasspointManager;
@Mock IDppCallback mDppCallback;
@Mock ILocalOnlyHotspotCallback mLohsCallback;
@Mock ICoexCallback mCoexCallback;
@Mock IScanResultsCallback mScanResultsCallback;
@Mock ISuggestionConnectionStatusListener mSuggestionConnectionStatusListener;
@Mock ISuggestionUserApprovalStatusListener mSuggestionUserApprovalStatusListener;
@Mock IOnWifiActivityEnergyInfoListener mOnWifiActivityEnergyInfoListener;
@Mock ISubsystemRestartCallback mSubsystemRestartCallback;
@Mock IWifiConnectedNetworkScorer mWifiConnectedNetworkScorer;
@Mock WifiSettingsConfigStore mWifiSettingsConfigStore;
@Mock WifiScanAlwaysAvailableSettingsCompatibility mScanAlwaysAvailableSettingsCompatibility;
@Mock PackageInfo mPackageInfo;
@Mock WifiConnectivityManager mWifiConnectivityManager;
@Mock WifiDataStall mWifiDataStall;
@Mock WifiNative mWifiNative;
@Mock ConnectHelper mConnectHelper;
@Mock IActionListener mActionListener;
@Mock WifiNetworkFactory mWifiNetworkFactory;
@Mock UntrustedWifiNetworkFactory mUntrustedWifiNetworkFactory;
@Mock OemWifiNetworkFactory mOemWifiNetworkFactory;
@Mock WifiDiagnostics mWifiDiagnostics;
@Mock WifiP2pConnection mWifiP2pConnection;
@Mock SimRequiredNotifier mSimRequiredNotifier;
@Mock WifiGlobals mWifiGlobals;
@Mock AdaptiveConnectivityEnabledSettingObserver mAdaptiveConnectivityEnabledSettingObserver;
@Mock MakeBeforeBreakManager mMakeBeforeBreakManager;
@Mock WifiCarrierInfoManager mWifiCarrierInfoManager;
@Mock OpenNetworkNotifier mOpenNetworkNotifier;
@Mock WifiNotificationManager mWifiNotificationManager;
@Mock SarManager mSarManager;
@Mock SelfRecovery mSelfRecovery;
@Mock LastCallerInfoManager mLastCallerInfoManager;
@Mock BuildProperties mBuildProperties;
@Mock LinkProbeManager mLinkProbeManager;
@Captor ArgumentCaptor<Intent> mIntentCaptor;
@Captor ArgumentCaptor<Runnable> mOnStoppedListenerCaptor;
WifiConfiguration mWifiConfig;
WifiLog mLog;
@Before public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
mLog = spy(new LogcatLog(TAG));
mLooper = new TestLooper();
mApplicationInfo = new ApplicationInfo();
mApplicationInfo.targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT;
when(mResources.getInteger(
eq(R.integer.config_wifiHardwareSoftapMaxClientCount)))
.thenReturn(10);
WifiInjector.sWifiInjector = mWifiInjector;
when(mRequestInfo.getPid()).thenReturn(mPid);
when(mRequestInfo2.getPid()).thenReturn(mPid2);
when(mWifiInjector.getUserManager()).thenReturn(mUserManager);
when(mWifiInjector.getWifiCountryCode()).thenReturn(mWifiCountryCode);
when(mWifiInjector.getWifiMetrics()).thenReturn(mWifiMetrics);
when(mWifiInjector.getWifiNetworkFactory()).thenReturn(mWifiNetworkFactory);
when(mWifiInjector.getUntrustedWifiNetworkFactory())
.thenReturn(mUntrustedWifiNetworkFactory);
when(mWifiInjector.getOemWifiNetworkFactory()).thenReturn(mOemWifiNetworkFactory);
when(mWifiInjector.getWifiDiagnostics()).thenReturn(mWifiDiagnostics);
when(mWifiInjector.getActiveModeWarden()).thenReturn(mActiveModeWarden);
when(mWifiInjector.getWifiHandlerThread()).thenReturn(mHandlerThread);
when(mWifiInjector.getMakeBeforeBreakManager()).thenReturn(mMakeBeforeBreakManager);
when(mWifiInjector.getWifiNotificationManager()).thenReturn(mWifiNotificationManager);
when(mWifiInjector.getBuildProperties()).thenReturn(mBuildProperties);
when(mWifiInjector.getLinkProbeManager()).thenReturn(mLinkProbeManager);
when(mHandlerThread.getThreadHandler()).thenReturn(new Handler(mLooper.getLooper()));
when(mHandlerThread.getLooper()).thenReturn(mLooper.getLooper());
when(mContext.getResources()).thenReturn(mResources);
when(mContext.getContentResolver()).thenReturn(mContentResolver);
when(mContext.getPackageManager()).thenReturn(mPackageManager);
when(mPackageManager.getPackageInfo(anyString(), anyInt())).thenReturn(mPackageInfo);
when(mPackageManager.checkSignatures(anyInt(), anyInt()))
.thenReturn(PackageManager.SIGNATURE_NO_MATCH);
when(mWifiInjector.getWifiApConfigStore()).thenReturn(mWifiApConfigStore);
doNothing().when(mFrameworkFacade).registerContentObserver(eq(mContext), any(),
anyBoolean(), any());
when(mFrameworkFacade.getSettingsWorkSource(any())).thenReturn(TEST_SETTINGS_WORKSOURCE);
when(mContext.getSystemService(Context.ACTIVITY_SERVICE)).thenReturn(mActivityManager);
when(mContext.getSystemService(Context.APP_OPS_SERVICE)).thenReturn(mAppOpsManager);
IPowerManager powerManagerService = mock(IPowerManager.class);
IThermalService thermalService = mock(IThermalService.class);
mPowerManager =
new PowerManager(mContext, powerManagerService, thermalService, new Handler());
when(mContext.getSystemServiceName(PowerManager.class)).thenReturn(Context.POWER_SERVICE);
when(mContext.getSystemService(PowerManager.class)).thenReturn(mPowerManager);
when(mContext.createContextAsUser(eq(UserHandle.CURRENT), anyInt()))
.thenReturn(mContextAsUser);
when(mWifiInjector.getFrameworkFacade()).thenReturn(mFrameworkFacade);
when(mWifiInjector.getWifiLockManager()).thenReturn(mLockManager);
when(mWifiInjector.getWifiMulticastLockManager()).thenReturn(mWifiMulticastLockManager);
when(mWifiInjector.getWifiLastResortWatchdog()).thenReturn(mWifiLastResortWatchdog);
when(mWifiInjector.getWifiBackupRestore()).thenReturn(mWifiBackupRestore);
when(mWifiInjector.getSoftApBackupRestore()).thenReturn(mSoftApBackupRestore);
when(mWifiInjector.makeLog(anyString())).thenReturn(mLog);
when(mWifiInjector.getWifiTrafficPoller()).thenReturn(mWifiTrafficPoller);
when(mWifiInjector.getWifiPermissionsUtil()).thenReturn(mWifiPermissionsUtil);
when(mWifiInjector.getWifiPermissionsWrapper()).thenReturn(mWifiPermissionsWrapper);
when(mWifiInjector.getWifiSettingsStore()).thenReturn(mSettingsStore);
when(mWifiInjector.getClock()).thenReturn(mClock);
when(mWifiInjector.getScanRequestProxy()).thenReturn(mScanRequestProxy);
when(mWifiInjector.getWakeupController()).thenReturn(mWakeupController);
when(mWifiInjector.getWifiNetworkSuggestionsManager())
.thenReturn(mWifiNetworkSuggestionsManager);
when(mWifiInjector.makeTelephonyManager()).thenReturn(mTelephonyManager);
when(mContext.getSystemService(TelephonyManager.class)).thenReturn(mTelephonyManager);
when(mWifiInjector.getCoexManager()).thenReturn(mCoexManager);
when(mWifiInjector.getWifiConfigManager()).thenReturn(mWifiConfigManager);
when(mWifiInjector.getPasspointManager()).thenReturn(mPasspointManager);
when(mActiveModeWarden.getPrimaryClientModeManager()).thenReturn(mClientModeManager);
when(mClientModeManager.getInterfaceName()).thenReturn(WIFI_IFACE_NAME);
when(mWifiInjector.getWifiScoreCard()).thenReturn(mWifiScoreCard);
when(mWifiInjector.getWifiHealthMonitor()).thenReturn(mWifiHealthMonitor);
when(mWifiInjector.getWifiNetworkScoreCache())
.thenReturn(mock(WifiNetworkScoreCache.class));
mWifiThreadRunner = new WifiThreadRunner(new Handler(mLooper.getLooper()));
mWifiThreadRunner.setTimeoutsAreErrors(true);
when(mWifiInjector.getWifiThreadRunner()).thenReturn(mWifiThreadRunner);
when(mWifiInjector.getSettingsConfigStore()).thenReturn(mWifiSettingsConfigStore);
when(mWifiInjector.getWifiScanAlwaysAvailableSettingsCompatibility())
.thenReturn(mScanAlwaysAvailableSettingsCompatibility);
when(mWifiInjector.getWifiConnectivityManager()).thenReturn(mWifiConnectivityManager);
when(mWifiInjector.getWifiDataStall()).thenReturn(mWifiDataStall);
when(mWifiInjector.getWifiNative()).thenReturn(mWifiNative);
when(mWifiInjector.getConnectHelper()).thenReturn(mConnectHelper);
when(mWifiInjector.getWifiP2pConnection()).thenReturn(mWifiP2pConnection);
when(mWifiInjector.getSimRequiredNotifier()).thenReturn(mSimRequiredNotifier);
when(mWifiInjector.getWifiGlobals()).thenReturn(mWifiGlobals);
when(mWifiInjector.getAdaptiveConnectivityEnabledSettingObserver())
.thenReturn(mAdaptiveConnectivityEnabledSettingObserver);
when(mClientModeManager.syncStartSubscriptionProvisioning(anyInt(),
any(OsuProvider.class), any(IProvisioningCallback.class))).thenReturn(true);
// Create an OSU provider that can be provisioned via an open OSU AP
mOsuProvider = PasspointProvisioningTestUtil.generateOsuProvider(true);
when(mContext.getOpPackageName()).thenReturn(TEST_PACKAGE_NAME);
when(mContext.getAttributionTag()).thenReturn(TEST_FEATURE_ID);
when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_DENIED);
when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETUP_WIZARD),
anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_DENIED);
when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_STACK),
anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_DENIED);
when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_MANAGED_PROVISIONING),
anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_DENIED);
when(mScanRequestProxy.startScan(anyInt(), anyString())).thenReturn(true);
when(mLohsCallback.asBinder()).thenReturn(mock(IBinder.class));
when(mWifiSettingsConfigStore.get(eq(WIFI_VERBOSE_LOGGING_ENABLED))).thenReturn(true);
when(mWifiPermissionsUtil.isSystem(anyString(), anyInt())).thenReturn(false);
when(mActiveModeWarden.getClientModeManagersInRoles(
ROLE_CLIENT_LOCAL_ONLY, ROLE_CLIENT_SECONDARY_LONG_LIVED))
.thenReturn(Collections.emptyList());
when(mWifiPermissionsUtil.doesUidBelongToCurrentUser(anyInt())).thenReturn(true);
when(mWifiInjector.getWifiCarrierInfoManager()).thenReturn(mWifiCarrierInfoManager);
when(mWifiInjector.getOpenNetworkNotifier()).thenReturn(mOpenNetworkNotifier);
when(mClientSoftApCallback.asBinder()).thenReturn(mAppBinder);
when(mAnotherSoftApCallback.asBinder()).thenReturn(mAnotherAppBinder);
when(mWifiInjector.getSarManager()).thenReturn(mSarManager);
mClientModeManagers = Arrays.asList(mClientModeManager, mock(ClientModeManager.class));
when(mActiveModeWarden.getClientModeManagers()).thenReturn(mClientModeManagers);
when(mWifiInjector.getSelfRecovery()).thenReturn(mSelfRecovery);
when(mWifiInjector.getLastCallerInfoManager()).thenReturn(mLastCallerInfoManager);
doAnswer(new AnswerWithArguments() {
public void answer(Runnable onStoppedListener) throws Throwable {
onStoppedListener.run();
}
}).when(mMakeBeforeBreakManager).stopAllSecondaryTransientClientModeManagers(any());
mWifiServiceImpl = makeWifiServiceImpl();
mDppCallback = new IDppCallback() {
@Override
public void onSuccessConfigReceived(int newNetworkId) throws RemoteException {
}
@Override
public void onSuccess(int status) throws RemoteException {
}
@Override
public void onFailure(int status, String ssid, String channelList, int[] bandList)
throws RemoteException {
}
@Override
public void onProgress(int status) throws RemoteException {
}
@Override
public void onBootstrapUriGenerated(String uri) throws RemoteException {
}
@Override
public IBinder asBinder() {
return null;
}
};
// permission not granted by default
doThrow(SecurityException.class).when(mContext).enforceCallingOrSelfPermission(
eq(Manifest.permission.NETWORK_SETUP_WIZARD), any());
mTestSoftApInfo = new SoftApInfo();
mTestSoftApInfo.setFrequency(TEST_AP_FREQUENCY);
mTestSoftApInfo.setBandwidth(TEST_AP_BANDWIDTH);
mTestSoftApInfo.setApInstanceIdentifier(WIFI_IFACE_NAME);
when(mWifiNative.getChannelsForBand(anyInt())).thenReturn(new int[0]);
mTestSoftApInfoList = new ArrayList<>();
mTestSoftApInfoList.add(mTestSoftApInfo);
mTestSoftApClients = new HashMap<>();
mTestSoftApClients.put(WIFI_IFACE_NAME, new ArrayList<WifiClient>());
mTestSoftApInfos = new HashMap<>();
mTestSoftApInfos.put(WIFI_IFACE_NAME, mTestSoftApInfo);
mWifiConfig = new WifiConfiguration();
mWifiConfig.SSID = TEST_SSID;
mWifiConfig.networkId = TEST_NETWORK_ID;
mWifiThreadRunner.prepareForAutoDispatch();
setup24GhzSupported();
}
/**
* Called after each test
*/
@After
public void cleanup() {
validateMockitoUsage();
}
private void stopAutoDispatchWithDispatchAllBeforeStopAndIgnoreExceptions(TestLooper looper) {
looper.dispatchAll();
looper.stopAutoDispatchAndIgnoreExceptions();
}
private WifiServiceImpl makeWifiServiceImpl() {
WifiServiceImpl wifiServiceImpl =
new WifiServiceImpl(mContext, mWifiInjector);
ArgumentCaptor<SoftApCallbackInternal> softApCallbackCaptor =
ArgumentCaptor.forClass(SoftApCallbackInternal.class);
verify(mActiveModeWarden, atLeastOnce()).registerSoftApCallback(
softApCallbackCaptor.capture());
mStateMachineSoftApCallback = softApCallbackCaptor.getValue();
ArgumentCaptor<SoftApCallbackInternal> lohsCallbackCaptor =
ArgumentCaptor.forClass(SoftApCallbackInternal.class);
mLohsInterfaceName = WIFI_IFACE_NAME;
verify(mActiveModeWarden, atLeastOnce()).registerLohsCallback(
lohsCallbackCaptor.capture());
mLohsApCallback = lohsCallbackCaptor.getValue();
mLooper.dispatchAll();
return wifiServiceImpl;
}
private WifiServiceImpl makeWifiServiceImplWithMockRunnerWhichTimesOut() {
WifiThreadRunner mockRunner = mock(WifiThreadRunner.class);
when(mockRunner.call(any(), any())).then(returnsSecondArg());
when(mockRunner.call(any(), any(int.class))).then(returnsSecondArg());
when(mockRunner.call(any(), any(boolean.class))).then(returnsSecondArg());
when(mockRunner.post(any())).thenReturn(false);
when(mWifiInjector.getWifiThreadRunner()).thenReturn(mockRunner);
// Reset mWifiCountryCode to avoid verify failure in makeWifiServiceImpl.
reset(mWifiCountryCode);
return makeWifiServiceImpl();
}
/**
* Test that REMOVE_NETWORK returns failure to public API when WifiConfigManager returns
* failure.
*/
@Test
public void testRemoveNetworkFailureAppBelowQSdk() {
doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManager)
.noteOp(AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Process.myUid(), TEST_PACKAGE_NAME,
TEST_FEATURE_ID, null);
when(mWifiPermissionsUtil.isTargetSdkLessThan(anyString(),
eq(Build.VERSION_CODES.Q), anyInt())).thenReturn(true);
when(mWifiConfigManager.removeNetwork(anyInt(), anyInt(), anyString())).thenReturn(false);
mLooper.startAutoDispatch();
boolean succeeded = mWifiServiceImpl.removeNetwork(0, TEST_PACKAGE_NAME);
mLooper.stopAutoDispatchAndIgnoreExceptions();
assertFalse(succeeded);
}
/**
* Ensure WifiMetrics.dump() is the only dump called when 'dumpsys wifi WifiMetricsProto' is
* called. This is required to support simple metrics collection via dumpsys
*/
@Test
public void testWifiMetricsDump() {
mLooper.startAutoDispatch();
mWifiServiceImpl.dump(new FileDescriptor(), new PrintWriter(new StringWriter()),
new String[]{mWifiMetrics.PROTO_DUMP_ARG});
mLooper.stopAutoDispatchAndIgnoreExceptions();
verify(mWifiMetrics).setEnhancedMacRandomizationForceEnabled(anyBoolean());
verify(mWifiMetrics).setIsScanningAlwaysEnabled(anyBoolean());
verify(mWifiMetrics).setVerboseLoggingEnabled(anyBoolean());
verify(mWifiMetrics)
.dump(any(FileDescriptor.class), any(PrintWriter.class), any(String[].class));
verify(mClientModeManager, never())
.dump(any(FileDescriptor.class), any(PrintWriter.class), any(String[].class));
}
/**
* Ensure WifiServiceImpl.dump() doesn't throw an NPE when executed with null args
*/
@Test
public void testDumpNullArgs() {
mLooper.startAutoDispatch();
mWifiServiceImpl.dump(new FileDescriptor(), new PrintWriter(new StringWriter()), null);
mLooper.stopAutoDispatchAndIgnoreExceptions();
verify(mWifiDiagnostics).captureBugReportData(
WifiDiagnostics.REPORT_REASON_USER_ACTION);
verify(mWifiDiagnostics).dump(any(), any(), any());
}
/**
* Verify that metrics is incremented correctly for Privileged Apps.
*/
@Test
public void testSetWifiEnabledMetricsPrivilegedApp() throws Exception {
when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED);
when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(true);
when(mSettingsStore.handleWifiToggled(anyBoolean())).thenReturn(true);
when(mSettingsStore.isAirplaneModeOn()).thenReturn(false);
InOrder inorder = inOrder(mWifiMetrics);
assertTrue(mWifiServiceImpl.setWifiEnabled(TEST_PACKAGE_NAME, true));
mLooper.dispatchAll();
assertTrue(mWifiServiceImpl.setWifiEnabled(TEST_PACKAGE_NAME, false));
mLooper.dispatchAll();
inorder.verify(mWifiMetrics).logUserActionEvent(UserActionEvent.EVENT_TOGGLE_WIFI_ON);
inorder.verify(mWifiMetrics).incrementNumWifiToggles(eq(true), eq(true));
inorder.verify(mWifiMetrics).logUserActionEvent(eq(UserActionEvent.EVENT_TOGGLE_WIFI_OFF),
anyInt());
inorder.verify(mWifiMetrics).incrementNumWifiToggles(eq(true), eq(false));
verify(mLastCallerInfoManager).put(eq(LastCallerInfoManager.WIFI_ENABLED), anyInt(),
anyInt(), anyInt(), anyString(), eq(false));
}
/**
* Verify that metrics is incremented correctly for normal Apps targeting pre-Q.
*/
@Test
public void testSetWifiEnabledMetricsNormalAppBelowQSdk() throws Exception {
doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManager)
.noteOp(AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Process.myUid(), TEST_PACKAGE_NAME);
when(mWifiPermissionsUtil.isTargetSdkLessThan(anyString(),
eq(Build.VERSION_CODES.Q), anyInt())).thenReturn(true);
when(mSettingsStore.handleWifiToggled(anyBoolean())).thenReturn(true);
when(mSettingsStore.isAirplaneModeOn()).thenReturn(false);
InOrder inorder = inOrder(mWifiMetrics);
assertTrue(mWifiServiceImpl.setWifiEnabled(TEST_PACKAGE_NAME, true));
assertTrue(mWifiServiceImpl.setWifiEnabled(TEST_PACKAGE_NAME, false));
inorder.verify(mWifiMetrics).incrementNumWifiToggles(eq(false), eq(true));
inorder.verify(mWifiMetrics).incrementNumWifiToggles(eq(false), eq(false));
}
/**
* Verify that metrics is not incremented by apps targeting Q SDK.
*/
@Test
public void testSetWifiEnabledMetricsNormalAppTargetingQSdkNoIncrement() throws Exception {
doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManager)
.noteOp(AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Process.myUid(), TEST_PACKAGE_NAME);
when(mWifiPermissionsUtil.isTargetSdkLessThan(anyString(),
eq(Build.VERSION_CODES.Q), anyInt())).thenReturn(false);
when(mSettingsStore.handleWifiToggled(eq(true))).thenReturn(true);
when(mSettingsStore.isAirplaneModeOn()).thenReturn(false);
assertFalse(mWifiServiceImpl.setWifiEnabled(TEST_PACKAGE_NAME, true));
assertFalse(mWifiServiceImpl.setWifiEnabled(TEST_PACKAGE_NAME, false));
verify(mWifiMetrics, never()).incrementNumWifiToggles(anyBoolean(), anyBoolean());
}
/**
* Verify that wifi can be enabled by a caller with NETWORK_SETTINGS permission.
*/
@Test
public void testSetWifiEnabledSuccessWithNetworkSettingsPermission() throws Exception {
when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED);
when(mSettingsStore.handleWifiToggled(eq(true))).thenReturn(true);
when(mSettingsStore.isAirplaneModeOn()).thenReturn(false);
assertTrue(mWifiServiceImpl.setWifiEnabled(TEST_PACKAGE_NAME, true));
verify(mActiveModeWarden).wifiToggled(
eq(new WorkSource(Binder.getCallingUid(), TEST_PACKAGE_NAME)));
}
/**
* Verify that wifi can be enabled by a caller with NETWORK_MANAGED_PROVISIONING permission.
*/
@Test
public void testSetWifiEnabledSuccessWithNetworkManagedProvisioningPermission()
throws Exception {
when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_MANAGED_PROVISIONING),
anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED);
when(mSettingsStore.handleWifiToggled(eq(true))).thenReturn(true);
when(mSettingsStore.isAirplaneModeOn()).thenReturn(false);
assertTrue(mWifiServiceImpl.setWifiEnabled(TEST_PACKAGE_NAME, true));
verify(mActiveModeWarden).wifiToggled(
eq(new WorkSource(Binder.getCallingUid(), TEST_PACKAGE_NAME)));
}
/**
* Verify that wifi can be enabled by the DO apps targeting Q SDK.
*/
@Test
public void testSetWifiEnabledSuccessForDOAppsTargetingQSdk() throws Exception {
doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManager)
.noteOp(AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Process.myUid(), TEST_PACKAGE_NAME);
when(mWifiPermissionsUtil.isTargetSdkLessThan(anyString(),
eq(Build.VERSION_CODES.Q), anyInt())).thenReturn(false);
when(mWifiPermissionsUtil.isDeviceOwner(Binder.getCallingUid(), TEST_PACKAGE_NAME))
.thenReturn(true);
when(mSettingsStore.handleWifiToggled(eq(true))).thenReturn(true);
when(mSettingsStore.isAirplaneModeOn()).thenReturn(false);
assertTrue(mWifiServiceImpl.setWifiEnabled(TEST_PACKAGE_NAME, true));
verify(mActiveModeWarden).wifiToggled(
eq(new WorkSource(Binder.getCallingUid(), TEST_PACKAGE_NAME)));
}
/**
* Verify that wifi can be enabled by the system apps targeting Q SDK.
*/
@Test
public void testSetWifiEnabledSuccessForSystemAppsTargetingQSdk() throws Exception {
doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManager)
.noteOp(AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Process.myUid(), TEST_PACKAGE_NAME);
when(mWifiPermissionsUtil.isTargetSdkLessThan(anyString(),
eq(Build.VERSION_CODES.Q), anyInt())).thenReturn(false);
when(mWifiPermissionsUtil.isSystem(anyString(), anyInt())).thenReturn(true);
when(mSettingsStore.handleWifiToggled(eq(true))).thenReturn(true);
when(mSettingsStore.isAirplaneModeOn()).thenReturn(false);
assertTrue(mWifiServiceImpl.setWifiEnabled(TEST_PACKAGE_NAME, true));
verify(mActiveModeWarden).wifiToggled(
eq(new WorkSource(Binder.getCallingUid(), TEST_PACKAGE_NAME)));
}
/**
* Verify that wifi can be enabled by the apps targeting pre-Q SDK.
*/
@Test
public void testSetWifiEnabledSuccessForAppsTargetingBelowQSdk() throws Exception {
doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManager)
.noteOp(AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Process.myUid(), TEST_PACKAGE_NAME);
when(mWifiPermissionsUtil.isTargetSdkLessThan(anyString(),
eq(Build.VERSION_CODES.Q), anyInt())).thenReturn(true);
when(mSettingsStore.handleWifiToggled(eq(true))).thenReturn(true);
when(mSettingsStore.isAirplaneModeOn()).thenReturn(false);
assertTrue(mWifiServiceImpl.setWifiEnabled(TEST_PACKAGE_NAME, true));
verify(mActiveModeWarden).wifiToggled(
eq(new WorkSource(Binder.getCallingUid(), TEST_PACKAGE_NAME)));
}
/**
* Verify that wifi cannot be enabled by the apps targeting Q SDK.
*/
@Test
public void testSetWifiEnabledFailureForAppsTargetingQSdk() throws Exception {
doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManager)
.noteOp(AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Process.myUid(), TEST_PACKAGE_NAME);
when(mWifiPermissionsUtil.isTargetSdkLessThan(anyString(),
eq(Build.VERSION_CODES.Q), anyInt())).thenReturn(false);
when(mSettingsStore.handleWifiToggled(eq(true))).thenReturn(true);
when(mSettingsStore.isAirplaneModeOn()).thenReturn(false);
assertFalse(mWifiServiceImpl.setWifiEnabled(TEST_PACKAGE_NAME, true));
verify(mActiveModeWarden, never()).wifiToggled(any());
}
/**
* Verify a SecurityException is thrown if OPSTR_CHANGE_WIFI_STATE is disabled for the app.
*/
@Test
public void testSetWifiEnableAppOpsRejected() throws Exception {
doThrow(new SecurityException()).when(mAppOpsManager)
.noteOp(AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Process.myUid(), TEST_PACKAGE_NAME);
when(mWifiPermissionsUtil.isTargetSdkLessThan(anyString(),
eq(Build.VERSION_CODES.Q), anyInt())).thenReturn(true);
when(mSettingsStore.handleWifiToggled(eq(true))).thenReturn(true);
try {
mWifiServiceImpl.setWifiEnabled(TEST_PACKAGE_NAME, true);
fail();
} catch (SecurityException e) {
}
verify(mActiveModeWarden, never()).wifiToggled(any());
}
/**
* Verify a SecurityException is thrown if OP_CHANGE_WIFI_STATE is set to MODE_IGNORED
* for the app.
*/
@Test // No exception expected, but the operation should not be done
public void testSetWifiEnableAppOpsIgnored() throws Exception {
doReturn(AppOpsManager.MODE_IGNORED).when(mAppOpsManager)
.noteOp(AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Process.myUid(), TEST_PACKAGE_NAME);
when(mWifiPermissionsUtil.isTargetSdkLessThan(anyString(),
eq(Build.VERSION_CODES.Q), anyInt())).thenReturn(true);
when(mSettingsStore.handleWifiToggled(eq(true))).thenReturn(true);
mWifiServiceImpl.setWifiEnabled(TEST_PACKAGE_NAME, true);
verify(mActiveModeWarden, never()).wifiToggled(any());
}
/**
* Verify that a call from an app with the NETWORK_SETTINGS permission can enable wifi if we
* are in airplane mode.
*/
@Test
public void testSetWifiEnabledFromNetworkSettingsHolderWhenInAirplaneMode() throws Exception {
when(mSettingsStore.handleWifiToggled(eq(true))).thenReturn(true);
when(mSettingsStore.isAirplaneModeOn()).thenReturn(true);
when(mContext.checkPermission(
eq(android.Manifest.permission.NETWORK_SETTINGS), anyInt(), anyInt()))
.thenReturn(PackageManager.PERMISSION_GRANTED);
assertTrue(mWifiServiceImpl.setWifiEnabled(SYSUI_PACKAGE_NAME, true));
verify(mActiveModeWarden).wifiToggled(
eq(new WorkSource(Binder.getCallingUid(), SYSUI_PACKAGE_NAME)));
}
/**
* Verify that a caller without the NETWORK_SETTINGS permission can't enable wifi
* if we are in airplane mode.
*/
@Test
public void testSetWifiEnabledFromAppFailsWhenInAirplaneMode() throws Exception {
doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManager)
.noteOp(AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Process.myUid(), TEST_PACKAGE_NAME);
when(mWifiPermissionsUtil.isTargetSdkLessThan(anyString(),
eq(Build.VERSION_CODES.Q), anyInt())).thenReturn(true);
when(mSettingsStore.handleWifiToggled(eq(true))).thenReturn(true);
when(mSettingsStore.isAirplaneModeOn()).thenReturn(true);
when(mContext.checkPermission(
eq(android.Manifest.permission.NETWORK_SETTINGS), anyInt(), anyInt()))
.thenReturn(PackageManager.PERMISSION_DENIED);
assertFalse(mWifiServiceImpl.setWifiEnabled(TEST_PACKAGE_NAME, true));
verify(mActiveModeWarden, never()).wifiToggled(any());
}
/**
* Helper to verify registering for state changes.
*/
private void verifyApRegistration() {
assertNotNull(mLohsApCallback);
}
/**
* Helper to emulate local-only hotspot state changes.
*
* Must call verifyApRegistration first.
*/
private void changeLohsState(int apState, int previousState, int error) {
// TestUtil.sendWifiApStateChanged(mBroadcastReceiverCaptor.getValue(), mContext,
// apState, previousState, error, WIFI_IFACE_NAME, IFACE_IP_MODE_LOCAL_ONLY);
mLohsApCallback.onStateChanged(apState, error);
}
/**
* Verify that a call from an app with the NETWORK_SETTINGS permission can enable wifi if we
* are in softap mode.
*/
@Test
public void testSetWifiEnabledFromNetworkSettingsHolderWhenApEnabled() throws Exception {
when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false);
mWifiServiceImpl.checkAndStartWifi();
mLooper.dispatchAll();
verifyApRegistration();
mStateMachineSoftApCallback.onStateChanged(WIFI_AP_STATE_ENABLED, 0);
when(mSettingsStore.handleWifiToggled(eq(true))).thenReturn(true);
when(mContext.checkPermission(
eq(android.Manifest.permission.NETWORK_SETTINGS), anyInt(), anyInt()))
.thenReturn(PackageManager.PERMISSION_GRANTED);
when(mSettingsStore.isAirplaneModeOn()).thenReturn(false);
assertTrue(mWifiServiceImpl.setWifiEnabled(SYSUI_PACKAGE_NAME, true));
verify(mActiveModeWarden).wifiToggled(
eq(new WorkSource(Binder.getCallingUid(), SYSUI_PACKAGE_NAME)));
}
/**
* Verify that a call from an app cannot enable wifi if we are in softap mode.
*/
@Test
public void testSetWifiEnabledFromAppFailsWhenApEnabled() throws Exception {
doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManager)
.noteOp(AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Process.myUid(), TEST_PACKAGE_NAME);
when(mWifiPermissionsUtil.isTargetSdkLessThan(anyString(),
eq(Build.VERSION_CODES.Q), anyInt())).thenReturn(true);
when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false);
mWifiServiceImpl.checkAndStartWifi();
mLooper.dispatchAll();
verifyApRegistration();
mStateMachineSoftApCallback.onStateChanged(WIFI_AP_STATE_ENABLED, 0);
when(mContext.checkPermission(
eq(android.Manifest.permission.NETWORK_SETTINGS), anyInt(), anyInt()))
.thenReturn(PackageManager.PERMISSION_DENIED);
when(mSettingsStore.isAirplaneModeOn()).thenReturn(false);
assertFalse(mWifiServiceImpl.setWifiEnabled(TEST_PACKAGE_NAME, true));
verify(mSettingsStore, never()).handleWifiToggled(anyBoolean());
verify(mActiveModeWarden, never()).wifiToggled(any());
}
/**
* Verify that the CMD_TOGGLE_WIFI message won't be sent if wifi is already on.
*/
@Test
public void testSetWifiEnabledNoToggle() throws Exception {
when(mSettingsStore.handleWifiToggled(eq(true))).thenReturn(false);
when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED);
assertTrue(mWifiServiceImpl.setWifiEnabled(TEST_PACKAGE_NAME, true));
verify(mActiveModeWarden, never()).wifiToggled(any());
}
/**
* Verify a SecurityException is thrown if a caller does not have the CHANGE_WIFI_STATE
* permission to toggle wifi.
*/
@Test
public void testSetWifiEnableWithoutChangeWifiStatePermission() throws Exception {
doThrow(new SecurityException()).when(mContext)
.enforceCallingOrSelfPermission(eq(android.Manifest.permission.CHANGE_WIFI_STATE),
eq("WifiService"));
try {
mWifiServiceImpl.setWifiEnabled(TEST_PACKAGE_NAME, true);
fail();
} catch (SecurityException e) {
}
}
/**
* Verify that wifi can be disabled by a caller with NETWORK_SETTINGS permission.
*/
@Test
public void testSetWifiDisabledSuccessWithNetworkSettingsPermission() throws Exception {
when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED);
when(mSettingsStore.handleWifiToggled(eq(false))).thenReturn(true);
assertTrue(mWifiServiceImpl.setWifiEnabled(TEST_PACKAGE_NAME, false));
verify(mActiveModeWarden).wifiToggled(
eq(new WorkSource(Binder.getCallingUid(), TEST_PACKAGE_NAME)));
}
/**
* Verify that wifi can be disabled by a caller with NETWORK_MANAGED_PROVISIONING permission.
*/
@Test
public void testSetWifiDisabledSuccessWithNetworkManagedProvisioningPermission()
throws Exception {
when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_MANAGED_PROVISIONING),
anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED);
when(mSettingsStore.handleWifiToggled(eq(false))).thenReturn(true);
assertTrue(mWifiServiceImpl.setWifiEnabled(TEST_PACKAGE_NAME, false));
verify(mActiveModeWarden).wifiToggled(
eq(new WorkSource(Binder.getCallingUid(), TEST_PACKAGE_NAME)));
}
/**
* Verify that wifi can be disabled by the PO apps targeting Q SDK.
*/
@Test
public void testSetWifiDisabledSuccessForPOAppsTargetingQSdk() throws Exception {
doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManager)
.noteOp(AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Process.myUid(), TEST_PACKAGE_NAME);
when(mWifiPermissionsUtil.isTargetSdkLessThan(anyString(),
eq(Build.VERSION_CODES.Q), anyInt())).thenReturn(false);
when(mWifiPermissionsUtil.isProfileOwner(Binder.getCallingUid(), TEST_PACKAGE_NAME))
.thenReturn(true);
when(mSettingsStore.handleWifiToggled(eq(false))).thenReturn(true);
when(mSettingsStore.isAirplaneModeOn()).thenReturn(false);
assertTrue(mWifiServiceImpl.setWifiEnabled(TEST_PACKAGE_NAME, false));
verify(mActiveModeWarden).wifiToggled(
eq(new WorkSource(Binder.getCallingUid(), TEST_PACKAGE_NAME)));
}
/**
* Verify that wifi can be disabled by the system apps targeting Q SDK.
*/
@Test
public void testSetWifiDisabledSuccessForSystemAppsTargetingQSdk() throws Exception {
doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManager)
.noteOp(AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Process.myUid(), TEST_PACKAGE_NAME);
when(mWifiPermissionsUtil.isTargetSdkLessThan(anyString(),
eq(Build.VERSION_CODES.Q), anyInt())).thenReturn(false);
when(mWifiPermissionsUtil.isSystem(anyString(), anyInt())).thenReturn(true);
when(mSettingsStore.handleWifiToggled(eq(false))).thenReturn(true);
when(mSettingsStore.isAirplaneModeOn()).thenReturn(false);
assertTrue(mWifiServiceImpl.setWifiEnabled(TEST_PACKAGE_NAME, false));
verify(mActiveModeWarden).wifiToggled(
eq(new WorkSource(Binder.getCallingUid(), TEST_PACKAGE_NAME)));
}
/**
* Verify that wifi can be disabled by the apps targeting pre-Q SDK.
*/
@Test
public void testSetWifiDisabledSuccessForAppsTargetingBelowQSdk() throws Exception {
doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManager)
.noteOp(AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Process.myUid(), TEST_PACKAGE_NAME);
when(mWifiPermissionsUtil.isTargetSdkLessThan(anyString(),
eq(Build.VERSION_CODES.Q), anyInt())).thenReturn(true);
when(mSettingsStore.handleWifiToggled(eq(false))).thenReturn(true);
when(mSettingsStore.isAirplaneModeOn()).thenReturn(false);
assertTrue(mWifiServiceImpl.setWifiEnabled(TEST_PACKAGE_NAME, false));
verify(mActiveModeWarden).wifiToggled(
eq(new WorkSource(Binder.getCallingUid(), TEST_PACKAGE_NAME)));
}
/**
* Verify that wifi cannot be disabled by the apps targeting Q SDK.
*/
@Test
public void testSetWifiDisabledFailureForAppsTargetingQSdk() throws Exception {
doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManager)
.noteOp(AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Process.myUid(), TEST_PACKAGE_NAME);
when(mWifiPermissionsUtil.isTargetSdkLessThan(anyString(),
eq(Build.VERSION_CODES.Q), anyInt())).thenReturn(false);
when(mSettingsStore.handleWifiToggled(eq(false))).thenReturn(true);
when(mSettingsStore.isAirplaneModeOn()).thenReturn(false);
assertFalse(mWifiServiceImpl.setWifiEnabled(TEST_PACKAGE_NAME, false));
verify(mActiveModeWarden, never()).wifiToggled(any());
}
/**
* Verify that CMD_TOGGLE_WIFI message won't be sent if wifi is already off.
*/
@Test
public void testSetWifiDisabledNoToggle() throws Exception {
when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED);
when(mSettingsStore.handleWifiToggled(eq(false))).thenReturn(false);
assertTrue(mWifiServiceImpl.setWifiEnabled(TEST_PACKAGE_NAME, false));
verify(mActiveModeWarden, never()).wifiToggled(any());
}
/**
* Verify a SecurityException is thrown if a caller does not have the CHANGE_WIFI_STATE
* permission to toggle wifi.
*/
@Test
public void testSetWifiDisabledWithoutChangeWifiStatePermission() throws Exception {
doThrow(new SecurityException()).when(mContext)
.enforceCallingOrSelfPermission(eq(android.Manifest.permission.CHANGE_WIFI_STATE),
eq("WifiService"));
try {
mWifiServiceImpl.setWifiEnabled(TEST_PACKAGE_NAME, false);
fail();
} catch (SecurityException e) { }
}
/**
* Verify that the restartWifiSubsystem fails w/o the NETWORK_AIRPLANE_MODE permission.
*/
@Test public void testRestartWifiSubsystemWithoutPermission() {
assumeTrue(SdkLevel.isAtLeastS());
doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission(
eq(android.Manifest.permission.RESTART_WIFI_SUBSYSTEM), eq("WifiService"));
try {
mWifiServiceImpl.restartWifiSubsystem();
fail("restartWifiSubsystem should fail w/o the APM permission!");
} catch (SecurityException e) {
// empty clause
}
}
/**
* Verify that a call to registerSubsystemRestartCallback throws a SecurityException if the
* caller does not have the ACCESS_WIFI_STATE permission.
*/
@Test
public void testRegisterSubsystemRestartThrowsSecurityExceptionOnMissingPermissions() {
assumeTrue(SdkLevel.isAtLeastS());
doThrow(new SecurityException()).when(mContext)
.enforceCallingOrSelfPermission(eq(ACCESS_WIFI_STATE),
eq("WifiService"));
try {
mWifiServiceImpl.registerSubsystemRestartCallback(mSubsystemRestartCallback);
fail("expected SecurityException");
} catch (SecurityException expected) { }
}
/**
* Verify that a call to unregisterSubsystemRestartCallback throws a SecurityException if the
* caller does not have the ACCESS_WIFI_STATE permission.
*/
@Test
public void testUnregisterSubsystemRestartThrowsSecurityExceptionOnMissingPermissions() {
assumeTrue(SdkLevel.isAtLeastS());
doThrow(new SecurityException()).when(mContext)
.enforceCallingOrSelfPermission(eq(ACCESS_WIFI_STATE),
eq("WifiService"));
try {
mWifiServiceImpl.unregisterSubsystemRestartCallback(mSubsystemRestartCallback);
fail("expected SecurityException");
} catch (SecurityException expected) { }
}
/**
* Test register and unregister subsystem restart callback will go to ActiveModeManager;
*/
@Test
public void testRegisterUnregisterSubsystemRestartCallback() throws Exception {
assumeTrue(SdkLevel.isAtLeastS());
when(mCoexCallback.asBinder()).thenReturn(mAppBinder);
mWifiServiceImpl.registerSubsystemRestartCallback(mSubsystemRestartCallback);
mLooper.dispatchAll();
verify(mActiveModeWarden).registerSubsystemRestartCallback(mSubsystemRestartCallback);
mWifiServiceImpl.unregisterSubsystemRestartCallback(mSubsystemRestartCallback);
mLooper.dispatchAll();
verify(mActiveModeWarden).unregisterSubsystemRestartCallback(mSubsystemRestartCallback);
}
/**
* Verify that the restartWifiSubsystem succeeds and passes correct parameters.
*/
@Test
public void testRestartWifiSubsystem() {
assumeTrue(SdkLevel.isAtLeastS());
when(mContext.checkPermission(eq(android.Manifest.permission.RESTART_WIFI_SUBSYSTEM),
anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED);
mWifiServiceImpl.restartWifiSubsystem();
mLooper.dispatchAll();
verify(mSelfRecovery).trigger(eq(REASON_API_CALL));
verify(mWifiMetrics).logUserActionEvent(eq(UserActionEvent.EVENT_RESTART_WIFI_SUB_SYSTEM),
anyInt());
}
/**
* Ensure unpermitted callers cannot write the SoftApConfiguration.
*/
@Test
public void testSetWifiApConfigurationNotSavedWithoutPermission() throws Exception {
when(mWifiPermissionsUtil.checkConfigOverridePermission(anyInt())).thenReturn(false);
WifiConfiguration apConfig = new WifiConfiguration();
try {
mWifiServiceImpl.setWifiApConfiguration(apConfig, TEST_PACKAGE_NAME);
fail("Expected SecurityException");
} catch (SecurityException e) { }
}
/**
* Ensure softap config is written when the caller has the correct permission.
*/
@Test
public void testSetWifiApConfigurationSuccess() throws Exception {
when(mWifiPermissionsUtil.checkConfigOverridePermission(anyInt())).thenReturn(true);
WifiConfiguration wifiApConfig = createValidWifiApConfiguration();
assertTrue(mWifiServiceImpl.setWifiApConfiguration(wifiApConfig, TEST_PACKAGE_NAME));
mLooper.dispatchAll();
verifyCheckChangePermission(TEST_PACKAGE_NAME);
verify(mWifiApConfigStore).setApConfiguration(eq(
ApConfigUtil.fromWifiConfiguration(wifiApConfig)));
}
/**
* Ensure that a null config does not overwrite the saved ap config.
*/
@Test
public void testSetWifiApConfigurationNullConfigNotSaved() throws Exception {
when(mWifiPermissionsUtil.checkConfigOverridePermission(anyInt())).thenReturn(true);
assertFalse(mWifiServiceImpl.setWifiApConfiguration(null, TEST_PACKAGE_NAME));
verify(mWifiApConfigStore, never()).setApConfiguration(isNull(SoftApConfiguration.class));
}
/**
* Ensure that an invalid config does not overwrite the saved ap config.
*/
@Test
public void testSetWifiApConfigurationWithInvalidConfigNotSaved() throws Exception {
when(mWifiPermissionsUtil.checkConfigOverridePermission(anyInt())).thenReturn(true);
assertFalse(mWifiServiceImpl.setWifiApConfiguration(new WifiConfiguration(),
TEST_PACKAGE_NAME));
verify(mWifiApConfigStore, never()).setApConfiguration(any());
}
/**
* Ensure unpermitted callers cannot write the SoftApConfiguration.
*/
@Test
public void testSetSoftApConfigurationNotSavedWithoutPermission() throws Exception {
SoftApConfiguration apConfig = createValidSoftApConfiguration();
try {
mWifiServiceImpl.setSoftApConfiguration(apConfig, TEST_PACKAGE_NAME);
fail("Expected SecurityException");
} catch (SecurityException e) { }
}
/**
* Ensure softap config is written when the caller has the correct permission.
*/
@Test
public void testSetSoftApConfigurationSuccessWithSettingPermission() throws Exception {
when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(true);
SoftApConfiguration apConfig = createValidSoftApConfiguration();
assertTrue(mWifiServiceImpl.setSoftApConfiguration(apConfig, TEST_PACKAGE_NAME));
mLooper.dispatchAll();
verify(mWifiApConfigStore).setApConfiguration(eq(apConfig));
verify(mActiveModeWarden).updateSoftApConfiguration(apConfig);
verify(mWifiPermissionsUtil).checkNetworkSettingsPermission(anyInt());
}
/**
* Ensure softap config is written when the caller has the correct permission.
*/
@Test
public void testSetSoftApConfigurationSuccessWithOverridePermission() throws Exception {
when(mWifiPermissionsUtil.checkConfigOverridePermission(anyInt())).thenReturn(true);
SoftApConfiguration apConfig = createValidSoftApConfiguration();
assertTrue(mWifiServiceImpl.setSoftApConfiguration(apConfig, TEST_PACKAGE_NAME));
mLooper.dispatchAll();
verify(mWifiApConfigStore).setApConfiguration(eq(apConfig));
verify(mActiveModeWarden).updateSoftApConfiguration(apConfig);
verify(mWifiPermissionsUtil).checkConfigOverridePermission(anyInt());
}
/**
* Ensure that a null config does not overwrite the saved ap config.
*/
@Test
public void testSetSoftApConfigurationNullConfigNotSaved() throws Exception {
when(mWifiPermissionsUtil.checkConfigOverridePermission(anyInt())).thenReturn(true);
assertFalse(mWifiServiceImpl.setSoftApConfiguration(null, TEST_PACKAGE_NAME));
verify(mWifiApConfigStore, never()).setApConfiguration(isNull(SoftApConfiguration.class));
verify(mActiveModeWarden, never()).updateSoftApConfiguration(any());
verify(mWifiPermissionsUtil).checkConfigOverridePermission(anyInt());
}
/**
* Ensure that an invalid config does not overwrite the saved ap config.
*/
@Test
public void testSetSoftApConfigurationWithInvalidConfigNotSaved() throws Exception {
when(mWifiPermissionsUtil.checkConfigOverridePermission(anyInt())).thenReturn(true);
assertFalse(mWifiServiceImpl.setSoftApConfiguration(
new SoftApConfiguration.Builder().build(), TEST_PACKAGE_NAME));
verify(mWifiApConfigStore, never()).setApConfiguration(any());
verify(mWifiPermissionsUtil).checkConfigOverridePermission(anyInt());
}
/**
* Ensure unpermitted callers are not able to retrieve the softap config.
*/
@Test
public void testGetSoftApConfigurationNotReturnedWithoutPermission() throws Exception {
try {
mWifiServiceImpl.getSoftApConfiguration();
fail("Expected a SecurityException");
} catch (SecurityException e) {
}
}
/**
* Ensure permitted callers are able to retrieve the softap config.
*/
@Test
public void testGetSoftApConfigurationSuccess() throws Exception {
when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false);
when(mWifiPermissionsUtil.checkConfigOverridePermission(anyInt())).thenReturn(true);
SoftApConfiguration apConfig = createValidSoftApConfiguration();
when(mWifiApConfigStore.getApConfiguration()).thenReturn(apConfig);
mLooper.startAutoDispatch();
assertThat(apConfig).isEqualTo(mWifiServiceImpl.getSoftApConfiguration());
mLooper.stopAutoDispatchAndIgnoreExceptions();
}
/**
* Ensure unpermitted callers are not able to retrieve the softap config.
*/
@Test
public void testGetWifiApConfigurationNotReturnedWithoutPermission() throws Exception {
when(mWifiPermissionsUtil.checkConfigOverridePermission(anyInt())).thenReturn(false);
try {
mWifiServiceImpl.getWifiApConfiguration();
fail("Expected a SecurityException");
} catch (SecurityException e) {
}
}
/**
* Ensure permitted callers are able to retrieve the softap config.
*/
@Test
public void testGetWifiApConfigurationSuccess() throws Exception {
when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false);
when(mWifiPermissionsUtil.checkConfigOverridePermission(anyInt())).thenReturn(true);
SoftApConfiguration apConfig = new SoftApConfiguration.Builder().build();
when(mWifiApConfigStore.getApConfiguration()).thenReturn(apConfig);
mLooper.startAutoDispatch();
WifiConfigurationTestUtil.assertConfigurationEqualForSoftAp(
apConfig.toWifiConfiguration(),
mWifiServiceImpl.getWifiApConfiguration());
mLooper.stopAutoDispatchAndIgnoreExceptions();
}
/**
* Ensure we return the proper variable for the softap state after getting an AP state change
* broadcast.
*/
@Test
public void testGetWifiApEnabled() throws Exception {
// ap should be disabled when wifi hasn't been started
assertEquals(WifiManager.WIFI_AP_STATE_DISABLED, mWifiServiceImpl.getWifiApEnabledState());
when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false);
mWifiServiceImpl.checkAndStartWifi();
mLooper.dispatchAll();
// ap should be disabled initially
assertEquals(WifiManager.WIFI_AP_STATE_DISABLED, mWifiServiceImpl.getWifiApEnabledState());
// send an ap state change to verify WifiServiceImpl is updated
verifyApRegistration();
mStateMachineSoftApCallback.onStateChanged(WIFI_AP_STATE_ENABLED, 0);
mStateMachineSoftApCallback.onStateChanged(WIFI_AP_STATE_FAILED, SAP_START_FAILURE_GENERAL);
mLooper.dispatchAll();
assertEquals(WifiManager.WIFI_AP_STATE_FAILED, mWifiServiceImpl.getWifiApEnabledState());
}
/**
* Ensure we do not allow unpermitted callers to get the wifi ap state.
*/
@Test
public void testGetWifiApEnabledPermissionDenied() {
// we should not be able to get the state
doThrow(new SecurityException()).when(mContext)
.enforceCallingOrSelfPermission(eq(ACCESS_WIFI_STATE),
eq("WifiService"));
try {
mWifiServiceImpl.getWifiApEnabledState();
fail("expected SecurityException");
} catch (SecurityException expected) { }
}
/**
* Make sure we do start WifiController (wifi disabled) if the device is already decrypted.
*/
@Test
public void testWifiControllerStartsWhenDeviceBootsWithWifiDisabled() {
when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false);
mWifiServiceImpl.checkAndStartWifi();
mLooper.dispatchAll();
verify(mWifiConfigManager).loadFromStore();
verify(mActiveModeWarden).start();
verify(mActiveModeWarden, never()).wifiToggled(any());
}
@Test
public void testWifiVerboseLoggingInitialization() {
when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false);
when(mWifiSettingsConfigStore.get(eq(WIFI_VERBOSE_LOGGING_ENABLED))).thenReturn(true);
mWifiServiceImpl.checkAndStartWifi();
mLooper.dispatchAll();
verify(mWifiConfigManager).loadFromStore();
verify(mActiveModeWarden).enableVerboseLogging(true);
// show key mode is always disabled at the beginning.
verify(mWifiGlobals).setShowKeyVerboseLoggingModeEnabled(eq(false));
verify(mActiveModeWarden).start();
}
/**
* Make sure we do start WifiController (wifi enabled) if the device is already decrypted.
*/
@Test
public void testWifiFullyStartsWhenDeviceBootsWithWifiEnabled() {
when(mSettingsStore.handleWifiToggled(true)).thenReturn(true);
when(mSettingsStore.isWifiToggleEnabled()).thenReturn(true);
when(mClientModeManager.syncGetWifiState()).thenReturn(WIFI_STATE_DISABLED);
when(mContext.getPackageName()).thenReturn(ANDROID_SYSTEM_PACKAGE);
when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED);
mWifiServiceImpl.checkAndStartWifi();
mLooper.dispatchAll();
verify(mWifiConfigManager).loadFromStore();
verify(mActiveModeWarden).start();
}
/**
* Verify that the setCoexUnsafeChannels calls the corresponding CoexManager API if
* the config_wifiDefaultCoexAlgorithmEnabled is false.
*/
@Test
public void testSetCoexUnsafeChannelsDefaultAlgorithmDisabled() {
assumeTrue(SdkLevel.isAtLeastS());
when(mResources.getBoolean(R.bool.config_wifiDefaultCoexAlgorithmEnabled))
.thenReturn(false);
List<CoexUnsafeChannel> unsafeChannels = new ArrayList<>();
unsafeChannels.addAll(Arrays.asList(new CoexUnsafeChannel(WIFI_BAND_24_GHZ, 6),
new CoexUnsafeChannel(WIFI_BAND_5_GHZ, 36)));
int coexRestrictions = COEX_RESTRICTION_SOFTAP
& COEX_RESTRICTION_WIFI_AWARE & COEX_RESTRICTION_WIFI_DIRECT;
mWifiServiceImpl.setCoexUnsafeChannels(unsafeChannels, coexRestrictions);
mLooper.dispatchAll();
verify(mCoexManager, times(1)).setCoexUnsafeChannels(any(), anyInt());
}
/**
* Verify that the setCoexUnsafeChannels does not call the corresponding CoexManager API if
* the config_wifiDefaultCoexAlgorithmEnabled is true.
*/
@Test
public void testSetCoexUnsafeChannelsDefaultAlgorithmEnabled() {
assumeTrue(SdkLevel.isAtLeastS());
when(mResources.getBoolean(R.bool.config_wifiDefaultCoexAlgorithmEnabled))
.thenReturn(true);
List<CoexUnsafeChannel> unsafeChannels = new ArrayList<>();
unsafeChannels.add(new CoexUnsafeChannel(WIFI_BAND_24_GHZ, 6));
unsafeChannels.add(new CoexUnsafeChannel(WIFI_BAND_5_GHZ, 36));
int coexRestrictions = COEX_RESTRICTION_SOFTAP
& COEX_RESTRICTION_WIFI_AWARE & COEX_RESTRICTION_WIFI_DIRECT;
mWifiServiceImpl.setCoexUnsafeChannels(unsafeChannels, coexRestrictions);
mLooper.dispatchAll();
verify(mCoexManager, never()).setCoexUnsafeChannels(any(), anyInt());
}
/**
* Verify that setCoexUnsafeChannels throws an IllegalArgumentException if passed a null set.
*/
@Test
public void testSetCoexUnsafeChannelsNullSet() {
assumeTrue(SdkLevel.isAtLeastS());
try {
mWifiServiceImpl.setCoexUnsafeChannels(null, 0);
fail("Expected IllegalArgumentException");
} catch (IllegalArgumentException e) {
}
}
/**
* Test register and unregister callback will go to CoexManager;
*/
@Test
public void testRegisterUnregisterCoexCallback() throws Exception {
assumeTrue(SdkLevel.isAtLeastS());
when(mCoexCallback.asBinder()).thenReturn(mAppBinder);
mWifiServiceImpl.registerCoexCallback(mCoexCallback);
mLooper.dispatchAll();
verify(mCoexManager).registerRemoteCoexCallback(mCoexCallback);
mWifiServiceImpl.unregisterCoexCallback(mCoexCallback);
mLooper.dispatchAll();
verify(mCoexManager).unregisterRemoteCoexCallback(mCoexCallback);
}
/**
* Verify that a call to setCoexUnsafeChannels throws a SecurityException if the caller does
* not have the WIFI_UPDATE_COEX_UNSAFE_CHANNELS permission.
*/
@Test
public void testSetCoexUnsafeChannelsThrowsSecurityExceptionOnMissingPermissions() {
assumeTrue(SdkLevel.isAtLeastS());
doThrow(new SecurityException()).when(mContext)
.enforceCallingOrSelfPermission(eq(WIFI_UPDATE_COEX_UNSAFE_CHANNELS),
eq("WifiService"));
try {
mWifiServiceImpl.setCoexUnsafeChannels(new ArrayList<>(), 0);
fail("expected SecurityException");
} catch (SecurityException expected) { }
}
/**
* Verify that a call to registerCoexCallback throws a SecurityException if the caller does
* not have the WIFI_ACCESS_COEX_UNSAFE_CHANNELS permission.
*/
@Test
public void testRegisterCoexCallbackThrowsSecurityExceptionOnMissingPermissions() {
assumeTrue(SdkLevel.isAtLeastS());
doThrow(new SecurityException()).when(mContext)
.enforceCallingOrSelfPermission(eq(WIFI_ACCESS_COEX_UNSAFE_CHANNELS),
eq("WifiService"));
try {
mWifiServiceImpl.registerCoexCallback(mCoexCallback);
fail("expected SecurityException");
} catch (SecurityException expected) { }
}
/**
* Verify that a call to unregisterCoexCallback throws a SecurityException if the caller does
* not have the WIFI_ACCESS_COEX_UNSAFE_CHANNELS permission.
*/
@Test
public void testUnregisterCoexCallbackThrowsSecurityExceptionOnMissingPermissions() {
assumeTrue(SdkLevel.isAtLeastS());
doThrow(new SecurityException()).when(mContext)
.enforceCallingOrSelfPermission(eq(WIFI_ACCESS_COEX_UNSAFE_CHANNELS),
eq("WifiService"));
try {
mWifiServiceImpl.unregisterCoexCallback(mCoexCallback);
fail("expected SecurityException");
} catch (SecurityException expected) { }
}
/**
* Verify caller with proper permission can call startSoftAp.
*/
@Test
public void testStartSoftApWithPermissionsAndNullConfig() {
mLooper.startAutoDispatch();
boolean result = mWifiServiceImpl.startSoftAp(null, TEST_PACKAGE_NAME);
mLooper.stopAutoDispatchAndIgnoreExceptions();
assertTrue(result);
verify(mActiveModeWarden).startSoftAp(mSoftApModeConfigCaptor.capture(),
eq(new WorkSource(Binder.getCallingUid(), TEST_PACKAGE_NAME)));
assertNull(mSoftApModeConfigCaptor.getValue().getSoftApConfiguration());
}
/**
* Verify caller with proper permissions but an invalid config does not start softap.
*/
@Test
public void testStartSoftApWithPermissionsAndInvalidConfig() {
mLooper.startAutoDispatch();
boolean result = mWifiServiceImpl.startSoftAp(mApConfig, TEST_PACKAGE_NAME);
mLooper.stopAutoDispatchAndIgnoreExceptions();
assertFalse(result);
verify(mActiveModeWarden, never()).startSoftAp(any(),
eq(new WorkSource(Binder.getCallingUid(), TEST_PACKAGE_NAME)));
}
/**
* Verify caller with proper permission and valid config does start softap.
*/
@Test
public void testStartSoftApWithPermissionsAndValidConfig() {
WifiConfiguration config = createValidWifiApConfiguration();
mLooper.startAutoDispatch();
boolean result = mWifiServiceImpl.startSoftAp(config, TEST_PACKAGE_NAME);
mLooper.stopAutoDispatchAndIgnoreExceptions();
assertTrue(result);
verify(mActiveModeWarden).startSoftAp(
mSoftApModeConfigCaptor.capture(),
eq(new WorkSource(Binder.getCallingUid(), TEST_PACKAGE_NAME)));
WifiConfigurationTestUtil.assertConfigurationEqualForSoftAp(
config,
mSoftApModeConfigCaptor.getValue().getSoftApConfiguration().toWifiConfiguration());
verify(mLastCallerInfoManager).put(eq(LastCallerInfoManager.SOFT_AP), anyInt(),
anyInt(), anyInt(), anyString(), eq(true));
}
/**
* Verify a SecurityException is thrown when a caller without the correct permission attempts to
* start softap.
*/
@Test(expected = SecurityException.class)
public void testStartSoftApWithoutPermissionThrowsException() throws Exception {
when(mContext.checkCallingOrSelfPermission(android.Manifest.permission.NETWORK_STACK))
.thenReturn(PackageManager.PERMISSION_DENIED);
doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission(
eq(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK), any());
mLooper.startAutoDispatch();
mWifiServiceImpl.startSoftAp(null, TEST_PACKAGE_NAME);
mLooper.stopAutoDispatchAndIgnoreExceptions();
}
/**
* Verify that startSoftAP() succeeds if the caller does not have the NETWORK_STACK permission
* but does have the MAINLINE_NETWORK_STACK permission.
*/
@Test
public void testStartSoftApWithoutNetworkStackWithMainlineNetworkStackSucceeds() {
when(mContext.checkCallingOrSelfPermission(android.Manifest.permission.NETWORK_STACK))
.thenReturn(PackageManager.PERMISSION_DENIED);
WifiConfiguration config = createValidWifiApConfiguration();
mLooper.startAutoDispatch();
boolean result = mWifiServiceImpl.startSoftAp(config, TEST_PACKAGE_NAME);
mLooper.stopAutoDispatchAndIgnoreExceptions();
assertTrue(result);
verify(mActiveModeWarden).startSoftAp(mSoftApModeConfigCaptor.capture(),
eq(new WorkSource(Binder.getCallingUid(), TEST_PACKAGE_NAME)));
WifiConfigurationTestUtil.assertConfigurationEqualForSoftAp(
config,
mSoftApModeConfigCaptor.getValue().getSoftApConfiguration().toWifiConfiguration());
verify(mContext).enforceCallingOrSelfPermission(
eq(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK), any());
}
/**
* Verify that startSoftAp() with valid config succeeds after a failed call
*/
@Test
public void testStartSoftApWithValidConfigSucceedsAfterFailure() {
// First initiate a failed call
mLooper.startAutoDispatch();
assertFalse(mWifiServiceImpl.startSoftAp(mApConfig, TEST_PACKAGE_NAME));
mLooper.stopAutoDispatchAndIgnoreExceptions();
verify(mActiveModeWarden, never()).startSoftAp(any(), any());
// Next attempt a valid config
WifiConfiguration config = createValidWifiApConfiguration();
mLooper.startAutoDispatch();
assertTrue(mWifiServiceImpl.startSoftAp(config, TEST_PACKAGE_NAME));
mLooper.stopAutoDispatchAndIgnoreExceptions();
verify(mActiveModeWarden).startSoftAp(mSoftApModeConfigCaptor.capture(),
eq(new WorkSource(Binder.getCallingUid(), TEST_PACKAGE_NAME)));
WifiConfigurationTestUtil.assertConfigurationEqualForSoftAp(
config,
mSoftApModeConfigCaptor.getValue().getSoftApConfiguration().toWifiConfiguration());
}
/**
* Verify caller with proper permission can call startTetheredHotspot.
*/
@Test
public void testStartTetheredHotspotWithPermissionsAndNullConfig() {
mLooper.startAutoDispatch();
boolean result = mWifiServiceImpl.startTetheredHotspot(null, TEST_PACKAGE_NAME);
mLooper.stopAutoDispatchAndIgnoreExceptions();
assertTrue(result);
verify(mActiveModeWarden).startSoftAp(mSoftApModeConfigCaptor.capture(),
eq(new WorkSource(Binder.getCallingUid(), TEST_PACKAGE_NAME)));
assertNull(mSoftApModeConfigCaptor.getValue().getSoftApConfiguration());
verify(mLastCallerInfoManager).put(eq(LastCallerInfoManager.TETHERED_HOTSPOT), anyInt(),
anyInt(), anyInt(), anyString(), eq(true));
}
/**
* Verify caller with proper permissions but an invalid config does not start softap.
*/
@Test
public void testStartTetheredHotspotWithPermissionsAndInvalidConfig() {
mLooper.startAutoDispatch();
boolean result = mWifiServiceImpl.startTetheredHotspot(
new SoftApConfiguration.Builder().build(), TEST_PACKAGE_NAME);
mLooper.stopAutoDispatchAndIgnoreExceptions();
assertFalse(result);
verify(mActiveModeWarden, never()).startSoftAp(any(), any());
}
/**
* Verify caller with proper permission and valid config does start softap.
*/
@Test
public void testStartTetheredHotspotWithPermissionsAndValidConfig() {
SoftApConfiguration config = createValidSoftApConfiguration();
mLooper.startAutoDispatch();
boolean result = mWifiServiceImpl.startTetheredHotspot(config, TEST_PACKAGE_NAME);
mLooper.stopAutoDispatchAndIgnoreExceptions();
assertTrue(result);
verify(mActiveModeWarden).startSoftAp(mSoftApModeConfigCaptor.capture(),
eq(new WorkSource(Binder.getCallingUid(), TEST_PACKAGE_NAME)));
assertThat(config).isEqualTo(mSoftApModeConfigCaptor.getValue().getSoftApConfiguration());
}
/**
* Verify isWifiBandSupported for 24GHz with an overlay override config
*/
@Test
public void testIsWifiBandSupported24gWithOverride() throws Exception {
when(mResources.getBoolean(R.bool.config_wifi24ghzSupport)).thenReturn(true);
mLooper.startAutoDispatch();
assertTrue(mWifiServiceImpl.is24GHzBandSupported());
mLooper.stopAutoDispatchAndIgnoreExceptions();
verify(mWifiNative, never()).getChannelsForBand(anyInt());
}
/**
* Verify isWifiBandSupported for 5GHz with an overlay override config
*/
@Test
public void testIsWifiBandSupported5gWithOverride() throws Exception {
when(mResources.getBoolean(R.bool.config_wifi5ghzSupport)).thenReturn(true);
mLooper.startAutoDispatch();
assertTrue(mWifiServiceImpl.is5GHzBandSupported());
mLooper.stopAutoDispatchAndIgnoreExceptions();
verify(mWifiNative, never()).getChannelsForBand(anyInt());
}
/**
* Verify isWifiBandSupported for 6GHz with an overlay override config
*/
@Test
public void testIsWifiBandSupported6gWithOverride() throws Exception {
when(mResources.getBoolean(R.bool.config_wifi6ghzSupport)).thenReturn(true);
mLooper.startAutoDispatch();
assertTrue(mWifiServiceImpl.is6GHzBandSupported());
mLooper.stopAutoDispatchAndIgnoreExceptions();
verify(mWifiNative, never()).getChannelsForBand(anyInt());
}
/**
* Verify isWifiBandSupported for 24GHz with no overlay override config no channels
*/
@Test
public void testIsWifiBandSupported24gNoOverrideNoChannels() throws Exception {
final int[] emptyArray = {};
when(mResources.getBoolean(R.bool.config_wifi24ghzSupport)).thenReturn(false);
when(mWifiNative.getChannelsForBand(anyInt())).thenReturn(emptyArray);
mLooper.startAutoDispatch();
assertFalse(mWifiServiceImpl.is24GHzBandSupported());
mLooper.stopAutoDispatch();
verify(mWifiNative).getChannelsForBand(WifiScanner.WIFI_BAND_24_GHZ);
}
/**
* Verify isWifiBandSupported for 5GHz with no overlay override config no channels
*/
@Test
public void testIsWifiBandSupported5gNoOverrideNoChannels() throws Exception {
final int[] emptyArray = {};
when(mResources.getBoolean(R.bool.config_wifi5ghzSupport)).thenReturn(false);
when(mWifiNative.getChannelsForBand(anyInt())).thenReturn(emptyArray);
mLooper.startAutoDispatch();
assertFalse(mWifiServiceImpl.is5GHzBandSupported());
mLooper.stopAutoDispatch();
verify(mWifiNative).getChannelsForBand(WifiScanner.WIFI_BAND_5_GHZ);
}
/**
* Verify isWifiBandSupported for 24GHz with no overlay override config with channels
*/
@Test
public void testIsWifiBandSupported24gNoOverrideWithChannels() throws Exception {
final int[] channelArray = {2412};
when(mResources.getBoolean(R.bool.config_wifi24ghzSupport)).thenReturn(false);
when(mWifiNative.getChannelsForBand(anyInt())).thenReturn(channelArray);
mLooper.startAutoDispatch();
assertTrue(mWifiServiceImpl.is24GHzBandSupported());
mLooper.stopAutoDispatch();
verify(mWifiNative).getChannelsForBand(WifiScanner.WIFI_BAND_24_GHZ);
}
/**
* Verify isWifiBandSupported for 5GHz with no overlay override config with channels
*/
@Test
public void testIsWifiBandSupported5gNoOverrideWithChannels() throws Exception {
final int[] channelArray = {5170};
when(mResources.getBoolean(R.bool.config_wifi5ghzSupport)).thenReturn(false);
when(mWifiNative.getChannelsForBand(anyInt())).thenReturn(channelArray);
mLooper.startAutoDispatch();
assertTrue(mWifiServiceImpl.is5GHzBandSupported());
mLooper.stopAutoDispatch();
verify(mWifiNative).getChannelsForBand(WifiScanner.WIFI_BAND_5_GHZ);
}
/**
* Verify isWifiBandSupported for 6GHz with no overlay override config no channels
*/
@Test
public void testIsWifiBandSupported6gNoOverrideNoChannels() throws Exception {
final int[] emptyArray = {};
when(mResources.getBoolean(R.bool.config_wifi6ghzSupport)).thenReturn(false);
when(mWifiNative.getChannelsForBand(anyInt())).thenReturn(emptyArray);
mLooper.startAutoDispatch();
assertFalse(mWifiServiceImpl.is6GHzBandSupported());
mLooper.stopAutoDispatch();
verify(mWifiNative).getChannelsForBand(WifiScanner.WIFI_BAND_6_GHZ);
}
/**
* Verify isWifiBandSupported for 6GHz with no overlay override config with channels
*/
@Test
public void testIsWifiBandSupported6gNoOverrideWithChannels() throws Exception {
final int[] channelArray = {6420};
when(mResources.getBoolean(R.bool.config_wifi6ghzSupport)).thenReturn(false);
when(mWifiNative.getChannelsForBand(anyInt())).thenReturn(channelArray);
mLooper.startAutoDispatch();
assertTrue(mWifiServiceImpl.is6GHzBandSupported());
mLooper.stopAutoDispatch();
verify(mWifiNative).getChannelsForBand(WifiScanner.WIFI_BAND_6_GHZ);
}
private void setup24GhzSupported() {
when(mResources.getBoolean(R.bool.config_wifi24ghzSupport)).thenReturn(true);
when(mResources.getBoolean(R.bool.config_wifiSoftap24ghzSupported)).thenReturn(true);
}
private void setup24GhzUnsupported(boolean isOnlyUnsupportedSoftAp) {
when(mResources.getBoolean(R.bool.config_wifiSoftap24ghzSupported)).thenReturn(false);
if (!isOnlyUnsupportedSoftAp) {
when(mResources.getBoolean(R.bool.config_wifi24ghzSupport)).thenReturn(false);
when(mWifiNative.getChannelsForBand(WifiScanner.WIFI_BAND_24_GHZ))
.thenReturn(new int[0]);
}
}
private void setup5GhzSupported() {
when(mResources.getBoolean(R.bool.config_wifi5ghzSupport)).thenReturn(true);
when(mResources.getBoolean(R.bool.config_wifiSoftap5ghzSupported)).thenReturn(true);
}
private void setup5GhzUnsupported(boolean isOnlyUnsupportedSoftAp) {
when(mResources.getBoolean(R.bool.config_wifiSoftap5ghzSupported)).thenReturn(false);
if (!isOnlyUnsupportedSoftAp) {
when(mResources.getBoolean(R.bool.config_wifi5ghzSupport)).thenReturn(false);
when(mWifiNative.getChannelsForBand(WifiScanner.WIFI_BAND_5_GHZ))
.thenReturn(new int[0]);
}
}
private void setup6GhzSupported() {
when(mResources.getBoolean(R.bool.config_wifi6ghzSupport)).thenReturn(true);
when(mResources.getBoolean(R.bool.config_wifiSoftap6ghzSupported)).thenReturn(true);
}
private void setup6GhzUnsupported(boolean isOnlyUnsupportedSoftAp) {
when(mResources.getBoolean(R.bool.config_wifiSoftap6ghzSupported)).thenReturn(false);
if (!isOnlyUnsupportedSoftAp) {
when(mResources.getBoolean(R.bool.config_wifi6ghzSupport)).thenReturn(false);
when(mWifiNative.getChannelsForBand(WifiScanner.WIFI_BAND_6_GHZ))
.thenReturn(new int[0]);
}
}
private void setup60GhzSupported() {
when(mResources.getBoolean(R.bool.config_wifi60ghzSupport)).thenReturn(true);
when(mResources.getBoolean(R.bool.config_wifiSoftap60ghzSupported)).thenReturn(true);
}
private void setup60GhzUnsupported(boolean isOnlyUnsupportedSoftAp) {
when(mResources.getBoolean(R.bool.config_wifiSoftap60ghzSupported)).thenReturn(false);
if (!isOnlyUnsupportedSoftAp) {
when(mResources.getBoolean(R.bool.config_wifi60ghzSupport)).thenReturn(false);
when(mWifiNative.getChannelsForBand(WifiScanner.WIFI_BAND_60_GHZ))
.thenReturn(new int[0]);
}
}
/**
* Verify attempt to start softAp with a supported 24GHz band succeeds.
*/
@Test
public void testStartTetheredHotspotWithSupported24gBand() {
setup24GhzSupported();
SoftApConfiguration config = new SoftApConfiguration.Builder()
.setSsid("TestAp")
.setPassphrase("thisIsABadPassword", SoftApConfiguration.SECURITY_TYPE_WPA2_PSK)
.setBand(SoftApConfiguration.BAND_2GHZ)
.build();
mLooper.startAutoDispatch();
boolean result = mWifiServiceImpl.startTetheredHotspot(config, TEST_PACKAGE_NAME);
mLooper.stopAutoDispatchAndIgnoreExceptions();
assertTrue(result);
verify(mActiveModeWarden).startSoftAp(mSoftApModeConfigCaptor.capture(),
eq(new WorkSource(Binder.getCallingUid(), TEST_PACKAGE_NAME)));
assertThat(config).isEqualTo(mSoftApModeConfigCaptor.getValue().getSoftApConfiguration());
}
/**
* Verify attempt to start softAp with a non-supported 2.4GHz band fails.
*/
@Test
public void testStartTetheredHotspotWithUnSupported24gBand() {
setup24GhzUnsupported(false);
SoftApConfiguration config = new SoftApConfiguration.Builder()
.setSsid("TestAp")
.setPassphrase("thisIsABadPassword", SoftApConfiguration.SECURITY_TYPE_WPA2_PSK)
.setBand(SoftApConfiguration.BAND_2GHZ)
.build();
mLooper.startAutoDispatch();
boolean result = mWifiServiceImpl.startTetheredHotspot(config, TEST_PACKAGE_NAME);
mLooper.stopAutoDispatchAndIgnoreExceptions();
assertFalse(result);
verify(mActiveModeWarden, never()).startSoftAp(any(), any());
}
/**
* Verify attempt to start softAp with a non-supported 2.4GHz band fails.
*/
@Test
public void testStartTetheredHotspotWithUnSupportedSoftAp24gBand() {
setup24GhzSupported();
setup24GhzUnsupported(true);
SoftApConfiguration config = new SoftApConfiguration.Builder()
.setSsid("TestAp")
.setPassphrase("thisIsABadPassword", SoftApConfiguration.SECURITY_TYPE_WPA2_PSK)
.setBand(SoftApConfiguration.BAND_2GHZ)
.build();
mLooper.startAutoDispatch();
boolean result = mWifiServiceImpl.startTetheredHotspot(config, TEST_PACKAGE_NAME);
mLooper.stopAutoDispatchAndIgnoreExceptions();
assertFalse(result);
verify(mActiveModeWarden, never()).startSoftAp(any(), any());
}
/**
* Verify attempt to start softAp with a supported 5GHz band succeeds.
*/
@Test
public void testStartTetheredHotspotWithSupported5gBand() {
setup5GhzSupported();
SoftApConfiguration config = new SoftApConfiguration.Builder()
.setSsid("TestAp")
.setPassphrase("thisIsABadPassword", SoftApConfiguration.SECURITY_TYPE_WPA2_PSK)
.setBand(SoftApConfiguration.BAND_5GHZ)
.build();
mLooper.startAutoDispatch();
boolean result = mWifiServiceImpl.startTetheredHotspot(config, TEST_PACKAGE_NAME);
mLooper.stopAutoDispatchAndIgnoreExceptions();
assertTrue(result);
verify(mActiveModeWarden).startSoftAp(mSoftApModeConfigCaptor.capture(),
eq(new WorkSource(Binder.getCallingUid(), TEST_PACKAGE_NAME)));
assertThat(config).isEqualTo(mSoftApModeConfigCaptor.getValue().getSoftApConfiguration());
}
/**
* Verify attempt to start softAp with a non-supported 5GHz band fails.
*/
@Test
public void testStartTetheredHotspotWithUnSupported5gBand() {
setup5GhzUnsupported(false);
SoftApConfiguration config = new SoftApConfiguration.Builder()
.setSsid("TestAp")
.setPassphrase("thisIsABadPassword", SoftApConfiguration.SECURITY_TYPE_WPA2_PSK)
.setBand(SoftApConfiguration.BAND_5GHZ)
.build();
mLooper.startAutoDispatch();
boolean result = mWifiServiceImpl.startTetheredHotspot(config, TEST_PACKAGE_NAME);
mLooper.stopAutoDispatchAndIgnoreExceptions();
assertFalse(result);
verify(mActiveModeWarden, never()).startSoftAp(any(), any());
}
/**
* Verify attempt to start softAp with a non-supported 5GHz band fails.
*/
@Test
public void testStartTetheredHotspotWithUnSupportedSoftAp5gBand() {
setup5GhzSupported();
setup5GhzUnsupported(true);
SoftApConfiguration config = new SoftApConfiguration.Builder()
.setSsid("TestAp")
.setPassphrase("thisIsABadPassword", SoftApConfiguration.SECURITY_TYPE_WPA2_PSK)
.setBand(SoftApConfiguration.BAND_5GHZ)
.build();
mLooper.startAutoDispatch();
boolean result = mWifiServiceImpl.startTetheredHotspot(config, TEST_PACKAGE_NAME);
mLooper.stopAutoDispatchAndIgnoreExceptions();
assertFalse(result);
verify(mActiveModeWarden, never()).startSoftAp(any(), any());
}
/**
* Verify attempt to start softAp with a supported 6GHz band succeeds.
*/
@Test
public void testStartTetheredHotspotWithSupported6gBand() {
setup6GhzSupported();
SoftApConfiguration config = new SoftApConfiguration.Builder()
.setSsid("TestAp")
.setPassphrase("thisIsABadPassword", SoftApConfiguration.SECURITY_TYPE_WPA2_PSK)
.setBand(SoftApConfiguration.BAND_6GHZ)
.build();
mLooper.startAutoDispatch();
boolean result = mWifiServiceImpl.startTetheredHotspot(config, TEST_PACKAGE_NAME);
mLooper.stopAutoDispatchAndIgnoreExceptions();
assertTrue(result);
verify(mActiveModeWarden).startSoftAp(mSoftApModeConfigCaptor.capture(),
eq(new WorkSource(Binder.getCallingUid(), TEST_PACKAGE_NAME)));
assertThat(config).isEqualTo(mSoftApModeConfigCaptor.getValue().getSoftApConfiguration());
}
/**
* Verify attempt to start softAp with a non-supported 6GHz band fails.
*/
@Test
public void testStartTetheredHotspotWithUnSupported6gBand() {
setup6GhzUnsupported(false);
SoftApConfiguration config = new SoftApConfiguration.Builder()
.setSsid("TestAp")
.setPassphrase("thisIsABadPassword", SoftApConfiguration.SECURITY_TYPE_WPA2_PSK)
.setBand(SoftApConfiguration.BAND_6GHZ)
.build();
mLooper.startAutoDispatch();
boolean result = mWifiServiceImpl.startTetheredHotspot(config, TEST_PACKAGE_NAME);
mLooper.stopAutoDispatchAndIgnoreExceptions();
assertFalse(result);
verify(mActiveModeWarden, never()).startSoftAp(any(), any());
}
/**
* Verify attempt to start softAp with a non-supported 6GHz band fails.
*/
@Test
public void testStartTetheredHotspotWithUnSupportedSoftAp6gBand() {
setup6GhzSupported();
setup6GhzUnsupported(true);
SoftApConfiguration config = new SoftApConfiguration.Builder()
.setSsid("TestAp")
.setPassphrase("thisIsABadPassword", SoftApConfiguration.SECURITY_TYPE_WPA2_PSK)
.setBand(SoftApConfiguration.BAND_6GHZ)
.build();
mLooper.startAutoDispatch();
boolean result = mWifiServiceImpl.startTetheredHotspot(config, TEST_PACKAGE_NAME);
mLooper.stopAutoDispatchAndIgnoreExceptions();
assertFalse(result);
verify(mActiveModeWarden, never()).startSoftAp(any(), any());
}
/**
* Verify attempt to start softAp with a supported 60GHz band succeeds.
*/
@Test
public void testStartTetheredHotspotWithSupported60gBand() {
setup60GhzSupported();
SoftApConfiguration config = new SoftApConfiguration.Builder()
.setSsid("TestAp")
.setPassphrase("thisIsABadPassword", SoftApConfiguration.SECURITY_TYPE_WPA2_PSK)
.setBand(SoftApConfiguration.BAND_60GHZ)
.build();
mLooper.startAutoDispatch();
boolean result = mWifiServiceImpl.startTetheredHotspot(config, TEST_PACKAGE_NAME);
mLooper.stopAutoDispatchAndIgnoreExceptions();
assertTrue(result);
verify(mActiveModeWarden).startSoftAp(mSoftApModeConfigCaptor.capture(),
eq(new WorkSource(Binder.getCallingUid(), TEST_PACKAGE_NAME)));
assertThat(config).isEqualTo(mSoftApModeConfigCaptor.getValue().getSoftApConfiguration());
}
/**
* Verify attempt to start softAp with a non-supported 60GHz band fails.
*/
@Test
public void testStartTetheredHotspotWithUnSupported60gBand() {
setup60GhzUnsupported(false);
SoftApConfiguration config = new SoftApConfiguration.Builder()
.setSsid("TestAp")
.setPassphrase("thisIsABadPassword", SoftApConfiguration.SECURITY_TYPE_WPA2_PSK)
.setBand(SoftApConfiguration.BAND_60GHZ)
.build();
mLooper.startAutoDispatch();
boolean result = mWifiServiceImpl.startTetheredHotspot(config, TEST_PACKAGE_NAME);
mLooper.stopAutoDispatchAndIgnoreExceptions();
assertFalse(result);
verify(mActiveModeWarden, never()).startSoftAp(any(), any());
}
/**
* Verify attempt to start softAp with a non-supported 60GHz band fails.
*/
@Test
public void testStartTetheredHotspotWithUnSupportedSoftAp60gBand() {
setup60GhzSupported();
setup60GhzUnsupported(true);
SoftApConfiguration config = new SoftApConfiguration.Builder()
.setSsid("TestAp")
.setPassphrase("thisIsABadPassword", SoftApConfiguration.SECURITY_TYPE_WPA2_PSK)
.setBand(SoftApConfiguration.BAND_60GHZ)
.build();
mLooper.startAutoDispatch();
boolean result = mWifiServiceImpl.startTetheredHotspot(config, TEST_PACKAGE_NAME);
mLooper.stopAutoDispatchAndIgnoreExceptions();
assertFalse(result);
verify(mActiveModeWarden, never()).startSoftAp(any(), any());
}
/**
* Verify attempt to start softAp with a supported band succeeds.
*/
@Test
public void testStartTetheredHotspotWithSupportedBand() {
setup5GhzSupported();
SoftApConfiguration config = new SoftApConfiguration.Builder()
.setSsid("TestAp")
.setPassphrase("thisIsABadPassword", SoftApConfiguration.SECURITY_TYPE_WPA2_PSK)
.setBand(SoftApConfiguration.BAND_5GHZ)
.build();
mLooper.startAutoDispatch();
boolean result = mWifiServiceImpl.startTetheredHotspot(config, TEST_PACKAGE_NAME);
mLooper.stopAutoDispatchAndIgnoreExceptions();
assertTrue(result);
verify(mActiveModeWarden).startSoftAp(mSoftApModeConfigCaptor.capture(),
eq(new WorkSource(Binder.getCallingUid(), TEST_PACKAGE_NAME)));
assertThat(config).isEqualTo(mSoftApModeConfigCaptor.getValue().getSoftApConfiguration());
}
/**
* Verify a SecurityException is thrown when a caller without the correct permission attempts to
* start softap.
*/
@Test(expected = SecurityException.class)
public void testStartTetheredHotspotWithoutPermissionThrowsException() throws Exception {
when(mContext.checkCallingOrSelfPermission(android.Manifest.permission.NETWORK_STACK))
.thenReturn(PackageManager.PERMISSION_DENIED);
doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission(
eq(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK), any());
mWifiServiceImpl.startTetheredHotspot(null, TEST_PACKAGE_NAME);
}
/**
* Verify that startTetheredHotspot() succeeds if the caller does not have the
* NETWORK_STACK permission but does have the MAINLINE_NETWORK_STACK permission.
*/
@Test
public void testStartTetheredHotspotWithoutNetworkStackWithMainlineNetworkStackSucceeds() {
when(mContext.checkCallingOrSelfPermission(android.Manifest.permission.NETWORK_STACK))
.thenReturn(PackageManager.PERMISSION_DENIED);
SoftApConfiguration config = createValidSoftApConfiguration();
mLooper.startAutoDispatch();
boolean result = mWifiServiceImpl.startTetheredHotspot(config, TEST_PACKAGE_NAME);
assertTrue(result);
mLooper.stopAutoDispatchAndIgnoreExceptions();
verify(mActiveModeWarden).startSoftAp(mSoftApModeConfigCaptor.capture(),
eq(new WorkSource(Binder.getCallingUid(), TEST_PACKAGE_NAME)));
assertThat(config).isEqualTo(mSoftApModeConfigCaptor.getValue().getSoftApConfiguration());
verify(mContext).enforceCallingOrSelfPermission(
eq(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK), any());
}
/**
* Verify a valied call to startTetheredHotspot succeeds after a failed call.
*/
@Test
public void testStartTetheredHotspotWithValidConfigSucceedsAfterFailedCall() {
// First issue an invalid call
mLooper.startAutoDispatch();
assertFalse(mWifiServiceImpl.startTetheredHotspot(
new SoftApConfiguration.Builder().build(), TEST_PACKAGE_NAME));
mLooper.stopAutoDispatchAndIgnoreExceptions();
verify(mActiveModeWarden, never()).startSoftAp(any(), any());
// Now attempt a successful call
mLooper.startAutoDispatch();
assertTrue(mWifiServiceImpl.startTetheredHotspot(null, TEST_PACKAGE_NAME));
mLooper.stopAutoDispatchAndIgnoreExceptions();
verify(mActiveModeWarden).startSoftAp(mSoftApModeConfigCaptor.capture(),
eq(new WorkSource(Binder.getCallingUid(), TEST_PACKAGE_NAME)));
assertNull(mSoftApModeConfigCaptor.getValue().getSoftApConfiguration());
}
/**
* Verify caller with proper permission can call stopSoftAp.
*/
@Test
public void testStopSoftApWithPermissions() {
boolean result = mWifiServiceImpl.stopSoftAp();
assertTrue(result);
verify(mActiveModeWarden).stopSoftAp(WifiManager.IFACE_IP_MODE_TETHERED);
verify(mLastCallerInfoManager).put(eq(LastCallerInfoManager.SOFT_AP), anyInt(),
anyInt(), anyInt(), anyString(), eq(false));
}
/**
* Verify SecurityException is thrown when a caller without the correct permission attempts to
* stop softap.
*/
@Test(expected = SecurityException.class)
public void testStopSoftApWithoutPermissionThrowsException() throws Exception {
when(mContext.checkCallingOrSelfPermission(android.Manifest.permission.NETWORK_STACK))
.thenReturn(PackageManager.PERMISSION_DENIED);
doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission(
eq(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK), any());
mWifiServiceImpl.stopSoftAp();
}
/**
* Ensure that we handle app ops check failure when handling scan request.
*/
@Test
public void testStartScanFailureAppOpsIgnored() {
doReturn(AppOpsManager.MODE_IGNORED).when(mAppOpsManager)
.noteOp(AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Process.myUid(), SCAN_PACKAGE_NAME);
mLooper.startAutoDispatch();
assertFalse(mWifiServiceImpl.startScan(SCAN_PACKAGE_NAME, TEST_FEATURE_ID));
mLooper.stopAutoDispatchAndIgnoreExceptions();
verify(mScanRequestProxy, never()).startScan(Process.myUid(), SCAN_PACKAGE_NAME);
}
/**
* Ensure that we handle scan access permission check failure when handling scan request.
*/
@Test
public void testStartScanFailureInCanAccessScanResultsPermission() {
doThrow(new SecurityException()).when(mWifiPermissionsUtil)
.enforceCanAccessScanResults(SCAN_PACKAGE_NAME, TEST_FEATURE_ID, Process.myUid(),
null);
mLooper.startAutoDispatch();
assertFalse(mWifiServiceImpl.startScan(SCAN_PACKAGE_NAME, TEST_FEATURE_ID));
mLooper.stopAutoDispatchAndIgnoreExceptions();
verify(mScanRequestProxy, never()).startScan(Process.myUid(), SCAN_PACKAGE_NAME);
}
/**
* Ensure that we handle scan request failure when posting the runnable to handler fails.
*/
@Test
public void testStartScanFailureInRunWithScissors() {
mWifiServiceImpl = makeWifiServiceImplWithMockRunnerWhichTimesOut();
mLooper.startAutoDispatch();
assertFalse(mWifiServiceImpl.startScan(SCAN_PACKAGE_NAME, TEST_FEATURE_ID));
mLooper.stopAutoDispatchAndIgnoreExceptions();
verify(mScanRequestProxy, never()).startScan(anyInt(), eq(SCAN_PACKAGE_NAME));
}
/**
* Ensure that we handle scan request failure from ScanRequestProxy fails.
*/
@Test
public void testStartScanFailureFromScanRequestProxy() {
when(mScanRequestProxy.startScan(anyInt(), anyString())).thenReturn(false);
mLooper.startAutoDispatch();
assertFalse(mWifiServiceImpl.startScan(SCAN_PACKAGE_NAME, TEST_FEATURE_ID));
mLooper.stopAutoDispatchAndIgnoreExceptions();
verify(mScanRequestProxy).startScan(Binder.getCallingUid(), SCAN_PACKAGE_NAME);
}
private WifiInfo setupForGetConnectionInfo() {
WifiInfo wifiInfo = new WifiInfo();
wifiInfo.setSSID(WifiSsid.createFromAsciiEncoded(TEST_SSID));
wifiInfo.setBSSID(TEST_BSSID);
wifiInfo.setNetworkId(TEST_NETWORK_ID);
wifiInfo.setFQDN(TEST_FQDN);
wifiInfo.setProviderFriendlyName(TEST_FRIENDLY_NAME);
return wifiInfo;
}
private WifiInfo parcelingRoundTrip(WifiInfo wifiInfo) {
Parcel parcel = Parcel.obtain();
wifiInfo.writeToParcel(parcel, 0);
// Rewind the pointer to the head of the parcel.
parcel.setDataPosition(0);
return WifiInfo.CREATOR.createFromParcel(parcel);
}
/**
* Test that connected SSID and BSSID are not exposed to an app that does not have the
* appropriate permissions.
*/
@Test
public void testConnectedIdsAreHiddenFromAppWithoutPermission() throws Exception {
WifiInfo wifiInfo = setupForGetConnectionInfo();
when(mClientModeManager.syncRequestConnectionInfo()).thenReturn(wifiInfo);
doThrow(new SecurityException()).when(mWifiPermissionsUtil).enforceCanAccessScanResults(
anyString(), nullable(String.class), anyInt(), nullable(String.class));
mLooper.startAutoDispatch();
WifiInfo connectionInfo = parcelingRoundTrip(
mWifiServiceImpl.getConnectionInfo(TEST_PACKAGE, TEST_FEATURE_ID));
mLooper.stopAutoDispatchAndIgnoreExceptions();
assertEquals(WifiManager.UNKNOWN_SSID, connectionInfo.getSSID());
assertEquals(WifiInfo.DEFAULT_MAC_ADDRESS, connectionInfo.getBSSID());
assertEquals(WifiConfiguration.INVALID_NETWORK_ID, connectionInfo.getNetworkId());
assertNull(connectionInfo.getPasspointFqdn());
assertNull(connectionInfo.getPasspointProviderFriendlyName());
if (SdkLevel.isAtLeastS()) {
try {
connectionInfo.isPrimary();
fail();
} catch (SecurityException e) { /* pass */ }
}
}
/**
* Test that connected SSID and BSSID are not exposed to an app that does not have the
* appropriate permissions, when enforceCanAccessScanResults raises a SecurityException.
*/
@Test
public void testConnectedIdsAreHiddenOnSecurityException() throws Exception {
WifiInfo wifiInfo = setupForGetConnectionInfo();
when(mClientModeManager.syncRequestConnectionInfo()).thenReturn(wifiInfo);
doThrow(new SecurityException()).when(mWifiPermissionsUtil).enforceCanAccessScanResults(
anyString(), nullable(String.class), anyInt(), nullable(String.class));
mLooper.startAutoDispatch();
WifiInfo connectionInfo = parcelingRoundTrip(
mWifiServiceImpl.getConnectionInfo(TEST_PACKAGE, TEST_FEATURE_ID));
mLooper.stopAutoDispatchAndIgnoreExceptions();
assertEquals(WifiManager.UNKNOWN_SSID, connectionInfo.getSSID());
assertEquals(WifiInfo.DEFAULT_MAC_ADDRESS, connectionInfo.getBSSID());
assertEquals(WifiConfiguration.INVALID_NETWORK_ID, connectionInfo.getNetworkId());
assertNull(connectionInfo.getPasspointFqdn());
assertNull(connectionInfo.getPasspointProviderFriendlyName());
}
/**
* Test that connected SSID and BSSID are exposed to an app that does have the
* appropriate permissions.
*/
@Test
public void testConnectedIdsAreVisibleFromPermittedApp() throws Exception {
WifiInfo wifiInfo = setupForGetConnectionInfo();
when(mClientModeManager.syncRequestConnectionInfo()).thenReturn(wifiInfo);
mLooper.startAutoDispatch();
WifiInfo connectionInfo = parcelingRoundTrip(
mWifiServiceImpl.getConnectionInfo(TEST_PACKAGE, TEST_FEATURE_ID));
mLooper.stopAutoDispatchAndIgnoreExceptions();
assertEquals(TEST_SSID_WITH_QUOTES, connectionInfo.getSSID());
assertEquals(TEST_BSSID, connectionInfo.getBSSID());
assertEquals(TEST_NETWORK_ID, WifiConfigurationUtil.removeSecurityTypeFromNetworkId(
connectionInfo.getNetworkId()));
assertEquals(TEST_FQDN, connectionInfo.getPasspointFqdn());
assertEquals(TEST_FRIENDLY_NAME, connectionInfo.getPasspointProviderFriendlyName());
}
/**
* Test that connected SSID and BSSID for secondary CMM are exposed to an app that requests
* the second STA on a device that supports STA + STA.
*/
@Test
public void testConnectedIdsFromSecondaryCmmAreVisibleFromAppRequestingSecondaryCmm()
throws Exception {
WifiInfo wifiInfo = setupForGetConnectionInfo();
ConcreteClientModeManager secondaryCmm = mock(ConcreteClientModeManager.class);
when(secondaryCmm.getRequestorWs())
.thenReturn(new WorkSource(Binder.getCallingUid(), TEST_PACKAGE));
when(secondaryCmm.syncRequestConnectionInfo()).thenReturn(wifiInfo);
when(mActiveModeWarden.getClientModeManagersInRoles(
ROLE_CLIENT_LOCAL_ONLY, ROLE_CLIENT_SECONDARY_LONG_LIVED))
.thenReturn(Arrays.asList(secondaryCmm));
mLooper.startAutoDispatch();
WifiInfo connectionInfo = parcelingRoundTrip(
mWifiServiceImpl.getConnectionInfo(TEST_PACKAGE, TEST_FEATURE_ID));
mLooper.stopAutoDispatchAndIgnoreExceptions();
assertEquals(TEST_SSID_WITH_QUOTES, connectionInfo.getSSID());
assertEquals(TEST_BSSID, connectionInfo.getBSSID());
assertEquals(TEST_NETWORK_ID, WifiConfigurationUtil.removeSecurityTypeFromNetworkId(
connectionInfo.getNetworkId()));
assertEquals(TEST_FQDN, connectionInfo.getPasspointFqdn());
assertEquals(TEST_FRIENDLY_NAME, connectionInfo.getPasspointProviderFriendlyName());
}
/**
* Test that connected SSID and BSSID for primary CMM are exposed to an app that is not the one
* that requests the second STA on a device that supports STA + STA.
*/
@Test
public void testConnectedIdsFromPrimaryCmmAreVisibleFromAppNotRequestingSecondaryCmm()
throws Exception {
WifiInfo wifiInfo = setupForGetConnectionInfo();
when(mClientModeManager.syncRequestConnectionInfo()).thenReturn(wifiInfo);
ConcreteClientModeManager secondaryCmm = mock(ConcreteClientModeManager.class);
when(secondaryCmm.getRequestorWs())
.thenReturn(new WorkSource(Binder.getCallingUid(), TEST_PACKAGE_NAME_OTHER));
when(mActiveModeWarden.getClientModeManagersInRoles(
ROLE_CLIENT_LOCAL_ONLY, ROLE_CLIENT_SECONDARY_LONG_LIVED))
.thenReturn(Arrays.asList(secondaryCmm));
mLooper.startAutoDispatch();
WifiInfo connectionInfo = parcelingRoundTrip(
mWifiServiceImpl.getConnectionInfo(TEST_PACKAGE, TEST_FEATURE_ID));
mLooper.stopAutoDispatchAndIgnoreExceptions();
assertEquals(TEST_SSID_WITH_QUOTES, connectionInfo.getSSID());
assertEquals(TEST_BSSID, connectionInfo.getBSSID());
assertEquals(TEST_NETWORK_ID, WifiConfigurationUtil.removeSecurityTypeFromNetworkId(
connectionInfo.getNetworkId()));
assertEquals(TEST_FQDN, connectionInfo.getPasspointFqdn());
assertEquals(TEST_FRIENDLY_NAME, connectionInfo.getPasspointProviderFriendlyName());
}
/**
* Test that configured network list are exposed empty list to an app that does not have the
* appropriate permissions.
*/
@Test
public void testConfiguredNetworkListAreEmptyFromAppWithoutPermission() throws Exception {
when(mWifiConfigManager.getSavedNetworks(anyInt()))
.thenReturn(TEST_WIFI_CONFIGURATION_LIST);
// no permission = target SDK=Q && not a carrier app
when(mTelephonyManager.checkCarrierPrivilegesForPackageAnyPhone(anyString())).thenReturn(
TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS);
ParceledListSlice<WifiConfiguration> configs =
mWifiServiceImpl.getConfiguredNetworks(TEST_PACKAGE, TEST_FEATURE_ID, false);
assertEquals(0, configs.getList().size());
}
/**
* Test that configured network list are exposed empty list to an app that does not have the
* appropriate permissions, when enforceCanAccessScanResults raises a SecurityException.
*/
@Test
public void testConfiguredNetworkListAreEmptyOnSecurityException() throws Exception {
when(mWifiConfigManager.getSavedNetworks(anyInt()))
.thenReturn(TEST_WIFI_CONFIGURATION_LIST);
doThrow(new SecurityException()).when(mWifiPermissionsUtil).enforceCanAccessScanResults(
anyString(), nullable(String.class), anyInt(), nullable(String.class));
ParceledListSlice<WifiConfiguration> configs =
mWifiServiceImpl.getConfiguredNetworks(TEST_PACKAGE, TEST_FEATURE_ID, false);
assertEquals(0, configs.getList().size());
}
/**
* Test that configured network list are exposed to an app that does have the
* appropriate permissions.
*/
@Test
public void testConfiguredNetworkListAreVisibleFromPermittedApp() throws Exception {
when(mWifiConfigManager.getSavedNetworks(anyInt()))
.thenReturn(TEST_WIFI_CONFIGURATION_LIST);
when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED);
mLooper.startAutoDispatch();
ParceledListSlice<WifiConfiguration> configs =
mWifiServiceImpl.getConfiguredNetworks(TEST_PACKAGE, TEST_FEATURE_ID, false);
mLooper.stopAutoDispatchAndIgnoreExceptions();
verify(mWifiConfigManager).getSavedNetworks(eq(Process.WIFI_UID));
WifiConfigurationTestUtil.assertConfigurationsEqualForBackup(
TEST_WIFI_CONFIGURATION_LIST, configs.getList());
}
@Test(expected = SecurityException.class)
public void testGetCallerConfiguredNetworks_ThrowExceptionIfNotDoOrPO() {
when(mWifiPermissionsUtil.isDeviceOwner(Binder.getCallingUid(), TEST_PACKAGE_NAME))
.thenReturn(false);
when(mWifiPermissionsUtil.isProfileOwner(Binder.getCallingUid(), TEST_PACKAGE_NAME))
.thenReturn(false);
mWifiServiceImpl.getConfiguredNetworks(TEST_PACKAGE_NAME, TEST_FEATURE_ID, true);
}
@Test
public void testGetCallerConfiguredNetworks_ReturnsCallerNetworks() {
final int callerUid = Binder.getCallingUid();
WifiConfiguration callerNetwork0 = WifiConfigurationTestUtil.generateWifiConfig(
0, callerUid, "\"red\"", true, true, null, null, SECURITY_NONE);
WifiConfiguration callerNetwork1 = WifiConfigurationTestUtil.generateWifiConfig(
1, callerUid, "\"red\"", true, true, null, null, SECURITY_NONE);
WifiConfiguration nonCallerNetwork0 = WifiConfigurationTestUtil.generateWifiConfig(
2, 1200000, "\"blue\"", false, true, null, null, SECURITY_NONE);
WifiConfiguration nonCallerNetwork1 = WifiConfigurationTestUtil.generateWifiConfig(
3, 1100000, "\"cyan\"", true, true, null, null, SECURITY_NONE);
when(mWifiConfigManager.getSavedNetworks(anyInt())).thenReturn(Arrays.asList(
callerNetwork0, callerNetwork1, nonCallerNetwork0, nonCallerNetwork1));
// Caller does NOT need to have location permission to be able to retrieve its own networks.
doThrow(new SecurityException()).when(mWifiPermissionsUtil).enforceCanAccessScanResults(
anyString(), nullable(String.class), anyInt(), nullable(String.class));
when(mWifiPermissionsUtil.isProfileOwner(Binder.getCallingUid(), TEST_PACKAGE_NAME))
.thenReturn(true);
mLooper.startAutoDispatch();
ParceledListSlice<WifiConfiguration> configs =
mWifiServiceImpl.getConfiguredNetworks(TEST_PACKAGE_NAME, TEST_FEATURE_ID, true);
mLooper.stopAutoDispatchAndIgnoreExceptions();
WifiConfigurationTestUtil.assertConfigurationsEqualForBackup(
Arrays.asList(callerNetwork0, callerNetwork1), configs.getList());
}
/**
* Test that privileged network list are exposed null to an app that does not have the
* appropriate permissions.
*/
@Test
public void testPrivilegedConfiguredNetworkListAreEmptyFromAppWithoutPermission() {
when(mWifiConfigManager.getConfiguredNetworksWithPasswords())
.thenReturn(TEST_WIFI_CONFIGURATION_LIST);
doThrow(new SecurityException()).when(mWifiPermissionsUtil).enforceCanAccessScanResults(
anyString(), nullable(String.class), anyInt(), nullable(String.class));
mLooper.startAutoDispatch();
ParceledListSlice<WifiConfiguration> configs =
mWifiServiceImpl.getPrivilegedConfiguredNetworks(TEST_PACKAGE, TEST_FEATURE_ID);
mLooper.stopAutoDispatchAndIgnoreExceptions();
assertNull(configs);
}
/**
* Test that privileged network list are exposed null to an app that does not have the
* appropriate permissions, when enforceCanAccessScanResults raises a SecurityException.
*/
@Test
public void testPrivilegedConfiguredNetworkListAreEmptyOnSecurityException() {
when(mWifiConfigManager.getConfiguredNetworksWithPasswords())
.thenReturn(TEST_WIFI_CONFIGURATION_LIST);
doThrow(new SecurityException()).when(mWifiPermissionsUtil).enforceCanAccessScanResults(
anyString(), nullable(String.class), anyInt(), nullable(String.class));
mLooper.startAutoDispatch();
ParceledListSlice<WifiConfiguration> configs =
mWifiServiceImpl.getPrivilegedConfiguredNetworks(TEST_PACKAGE, TEST_FEATURE_ID);
mLooper.stopAutoDispatchAndIgnoreExceptions();
assertNull(configs);
}
/**
* Test that privileged network list are exposed to an app that does have the
* appropriate permissions (simulated by not throwing an exception for READ_WIFI_CREDENTIAL).
*/
@Test
public void testPrivilegedConfiguredNetworkListAreVisibleFromPermittedApp() {
when(mWifiConfigManager.getConfiguredNetworksWithPasswords())
.thenReturn(TEST_WIFI_CONFIGURATION_LIST);
mLooper.startAutoDispatch();
ParceledListSlice<WifiConfiguration> configs =
mWifiServiceImpl.getPrivilegedConfiguredNetworks(TEST_PACKAGE, TEST_FEATURE_ID);
mLooper.stopAutoDispatchAndIgnoreExceptions();
WifiConfigurationTestUtil.assertConfigurationsEqualForBackup(
TEST_WIFI_CONFIGURATION_LIST, configs.getList());
}
/**
* Test fetching of scan results.
*/
@Test
public void testGetScanResults() {
ScanResult[] scanResults =
ScanTestUtil.createScanDatas(new int[][]{{2417, 2427, 5180, 5170}})[0]
.getResults();
List<ScanResult> scanResultList =
new ArrayList<>(Arrays.asList(scanResults));
when(mScanRequestProxy.getScanResults()).thenReturn(scanResultList);
String packageName = "test.com";
String featureId = "test.com.featureId";
mLooper.startAutoDispatch();
List<ScanResult> retrievedScanResultList = mWifiServiceImpl.getScanResults(packageName,
featureId);
mLooper.stopAutoDispatchAndIgnoreExceptions();
verify(mScanRequestProxy).getScanResults();
ScanTestUtil.assertScanResultsEquals(scanResults,
retrievedScanResultList.toArray(new ScanResult[retrievedScanResultList.size()]));
}
/**
* Ensure that we handle scan results failure when posting the runnable to handler fails.
*/
@Test
public void testGetScanResultsFailureInRunWithScissors() {
mWifiServiceImpl = makeWifiServiceImplWithMockRunnerWhichTimesOut();
ScanResult[] scanResults =
ScanTestUtil.createScanDatas(new int[][]{{2417, 2427, 5180, 5170}})[0]
.getResults();
List<ScanResult> scanResultList =
new ArrayList<>(Arrays.asList(scanResults));
when(mScanRequestProxy.getScanResults()).thenReturn(scanResultList);
String packageName = "test.com";
String featureId = "test.com.featureId";
mLooper.startAutoDispatch();
List<ScanResult> retrievedScanResultList = mWifiServiceImpl.getScanResults(packageName,
featureId);
mLooper.stopAutoDispatchAndIgnoreExceptions();
verify(mScanRequestProxy, never()).getScanResults();
assertTrue(retrievedScanResultList.isEmpty());
}
/**
* Test fetching of matching scan results with provided WifiNetworkSuggestion, but it doesn't
* specify the scan results to be filtered.
*/
@Test
public void testGetMatchingScanResultsWithoutSpecifiedScanResults() {
ScanResult[] scanResults =
ScanTestUtil.createScanDatas(new int[][]{{2417, 2427, 5180, 5170}})[0]
.getResults();
List<ScanResult> scanResultList =
new ArrayList<>(Arrays.asList(scanResults));
when(mScanRequestProxy.getScanResults()).thenReturn(scanResultList);
WifiNetworkSuggestion mockSuggestion = mock(WifiNetworkSuggestion.class);
List<WifiNetworkSuggestion> matchingSuggestions = new ArrayList<>() {{
add(mockSuggestion);
}};
Map<WifiNetworkSuggestion, List<ScanResult>> result = new HashMap<>() {{
put(mockSuggestion, scanResultList);
}};
when(mWifiNetworkSuggestionsManager.getMatchingScanResults(eq(matchingSuggestions),
eq(scanResultList))).thenReturn(result);
String packageName = "test.com";
String featureId = "test.com.featureId";
mLooper.startAutoDispatch();
Map<WifiNetworkSuggestion, List<ScanResult>> retrievedScanResults =
mWifiServiceImpl.getMatchingScanResults(
matchingSuggestions, null, packageName, featureId);
mLooper.stopAutoDispatchAndIgnoreExceptions();
ScanTestUtil.assertScanResultsEquals(scanResults,
retrievedScanResults.get(mockSuggestion)
.toArray(new ScanResult[retrievedScanResults.size()]));
}
/**
* Test fetching of matching scan results with provided WifiNetworkSuggestion and ScanResults.
*/
@Test
public void testGetMatchingScanResultsWithSpecifiedScanResults() {
ScanResult[] scanResults =
ScanTestUtil.createScanDatas(new int[][]{{2417, 2427, 5180, 5170}})[0]
.getResults();
List<ScanResult> scanResultList =
new ArrayList<>(Arrays.asList(scanResults));
WifiNetworkSuggestion mockSuggestion = mock(WifiNetworkSuggestion.class);
List<WifiNetworkSuggestion> matchingSuggestions = new ArrayList<>() {{
add(mockSuggestion);
}};
Map<WifiNetworkSuggestion, List<ScanResult>> result = new HashMap<>() {{
put(mockSuggestion, scanResultList);
}};
when(mWifiNetworkSuggestionsManager.getMatchingScanResults(eq(matchingSuggestions),
eq(scanResultList))).thenReturn(result);
String packageName = "test.com";
String featureId = "test.com.featureId";
mLooper.startAutoDispatch();
Map<WifiNetworkSuggestion, List<ScanResult>> retrievedScanResults =
mWifiServiceImpl.getMatchingScanResults(
matchingSuggestions, scanResultList, packageName, featureId);
mLooper.stopAutoDispatchAndIgnoreExceptions();
ScanTestUtil.assertScanResultsEquals(scanResults,
retrievedScanResults.get(mockSuggestion)
.toArray(new ScanResult[retrievedScanResults.size()]));
}
/**
* Ensure that we handle failure when posting the runnable to handler fails.
*/
@Test
public void testGetMatchingScanResultsFailureInRunWithScissors() {
mWifiServiceImpl = makeWifiServiceImplWithMockRunnerWhichTimesOut();
ScanResult[] scanResults =
ScanTestUtil.createScanDatas(new int[][]{{2417, 2427, 5180, 5170}})[0]
.getResults();
List<ScanResult> scanResultList =
new ArrayList<>(Arrays.asList(scanResults));
when(mScanRequestProxy.getScanResults()).thenReturn(scanResultList);
WifiNetworkSuggestion mockSuggestion = mock(WifiNetworkSuggestion.class);
List<WifiNetworkSuggestion> matchingSuggestions = new ArrayList<>() {{
add(mockSuggestion);
}};
Map<WifiNetworkSuggestion, List<ScanResult>> result = new HashMap<>() {{
put(mockSuggestion, scanResultList);
}};
when(mWifiNetworkSuggestionsManager.getMatchingScanResults(eq(matchingSuggestions),
eq(scanResultList))).thenReturn(result);
String packageName = "test.com";
String featureId = "test.com.featureId";
mLooper.startAutoDispatch();
Map<WifiNetworkSuggestion, List<ScanResult>> retrievedScanResults =
mWifiServiceImpl.getMatchingScanResults(
matchingSuggestions, null, packageName, featureId);
mLooper.stopAutoDispatchAndIgnoreExceptions();
assertTrue(retrievedScanResults.isEmpty());
}
private void setupLohsPermissions() {
when(mWifiPermissionsUtil.isLocationModeEnabled()).thenReturn(true);
when(mFrameworkFacade.isAppForeground(any(), anyInt())).thenReturn(true);
when(mUserManager.hasUserRestrictionForUser(
eq(UserManager.DISALLOW_CONFIG_TETHERING), any()))
.thenReturn(false);
}
private void registerLOHSRequestFull() {
setupLohsPermissions();
int result = mWifiServiceImpl.startLocalOnlyHotspot(mLohsCallback, TEST_PACKAGE_NAME,
TEST_FEATURE_ID, null);
assertEquals(LocalOnlyHotspotCallback.REQUEST_REGISTERED, result);
verifyCheckChangePermission(TEST_PACKAGE_NAME);
}
/**
* Verify that the call to startLocalOnlyHotspot returns REQUEST_REGISTERED when successfully
* called.
*/
@Test
public void testStartLocalOnlyHotspotSingleRegistrationReturnsRequestRegistered() {
mLooper.startAutoDispatch();
registerLOHSRequestFull();
stopAutoDispatchWithDispatchAllBeforeStopAndIgnoreExceptions(mLooper);
// Use settings worksouce.
verify(mActiveModeWarden).startSoftAp(mSoftApModeConfigCaptor.capture(),
eq(TEST_SETTINGS_WORKSOURCE));
}
/**
* Verify that a call to startLocalOnlyHotspot throws a SecurityException if the caller does not
* have the CHANGE_WIFI_STATE permission.
*/
@Test(expected = SecurityException.class)
public void testStartLocalOnlyHotspotThrowsSecurityExceptionWithoutCorrectPermission() {
doThrow(new SecurityException()).when(mContext)
.enforceCallingOrSelfPermission(eq(android.Manifest.permission.CHANGE_WIFI_STATE),
eq("WifiService"));
mWifiServiceImpl.startLocalOnlyHotspot(
mLohsCallback, TEST_PACKAGE_NAME, TEST_FEATURE_ID, null);
}
/**
* Verify that a call to startLocalOnlyHotspot throws a SecurityException if the caller does not
* have Location permission.
*/
@Test(expected = SecurityException.class)
public void testStartLocalOnlyHotspotThrowsSecurityExceptionWithoutLocationPermission() {
doThrow(new SecurityException())
.when(mWifiPermissionsUtil).enforceLocationPermission(eq(TEST_PACKAGE_NAME),
eq(TEST_FEATURE_ID),
anyInt());
mWifiServiceImpl.startLocalOnlyHotspot(
mLohsCallback, TEST_PACKAGE_NAME, TEST_FEATURE_ID, null);
}
/**
* Verify that a call to startLocalOnlyHotspot throws a SecurityException if Location mode is
* disabled.
*/
@Test(expected = SecurityException.class)
public void testStartLocalOnlyHotspotThrowsSecurityExceptionWithoutLocationEnabled() {
when(mWifiPermissionsUtil.isLocationModeEnabled()).thenReturn(false);
mWifiServiceImpl.startLocalOnlyHotspot(
mLohsCallback, TEST_PACKAGE_NAME, TEST_FEATURE_ID, null);
}
/**
* Only start LocalOnlyHotspot if the caller is the foreground app at the time of the request.
*/
@Test
public void testStartLocalOnlyHotspotFailsIfRequestorNotForegroundApp() throws Exception {
when(mWifiPermissionsUtil.isLocationModeEnabled()).thenReturn(true);
when(mFrameworkFacade.isAppForeground(any(), anyInt())).thenReturn(false);
int result = mWifiServiceImpl.startLocalOnlyHotspot(
mLohsCallback, TEST_PACKAGE_NAME, TEST_FEATURE_ID, null);
assertEquals(LocalOnlyHotspotCallback.ERROR_INCOMPATIBLE_MODE, result);
}
/**
* Only start tethering if we are not tethering.
*/
@Test
public void testTetheringDoesNotStartWhenAlreadyTetheringActive() throws Exception {
WifiConfiguration config = createValidWifiApConfiguration();
mLooper.startAutoDispatch();
assertTrue(mWifiServiceImpl.startSoftAp(config, TEST_PACKAGE_NAME));
mLooper.stopAutoDispatchAndIgnoreExceptions();
verify(mActiveModeWarden).startSoftAp(mSoftApModeConfigCaptor.capture(),
eq(new WorkSource(Binder.getCallingUid(), TEST_PACKAGE_NAME)));
WifiConfigurationTestUtil.assertConfigurationEqualForSoftAp(
config,
mSoftApModeConfigCaptor.getValue().getSoftApConfiguration().toWifiConfiguration());
mStateMachineSoftApCallback.onStateChanged(WIFI_AP_STATE_ENABLED, 0);
mWifiServiceImpl.updateInterfaceIpState(WIFI_IFACE_NAME, IFACE_IP_MODE_TETHERED);
mLooper.dispatchAll();
assertEquals(WIFI_AP_STATE_ENABLED, mWifiServiceImpl.getWifiApEnabledState());
reset(mActiveModeWarden);
// Start another session without a stop, that should fail.
mLooper.startAutoDispatch();
assertFalse(mWifiServiceImpl.startSoftAp(
createValidWifiApConfiguration(), TEST_PACKAGE_NAME));
mLooper.stopAutoDispatchAndIgnoreExceptions();
verifyNoMoreInteractions(mActiveModeWarden);
}
/**
* Only start tethering if we are not tethering in new API: startTetheredHotspot.
*/
@Test
public void testStartTetheredHotspotDoesNotStartWhenAlreadyTetheringActive() throws Exception {
SoftApConfiguration config = createValidSoftApConfiguration();
mLooper.startAutoDispatch();
assertTrue(mWifiServiceImpl.startTetheredHotspot(config, TEST_PACKAGE_NAME));
mLooper.stopAutoDispatch();
verify(mActiveModeWarden).startSoftAp(mSoftApModeConfigCaptor.capture(),
eq(new WorkSource(Binder.getCallingUid(), TEST_PACKAGE_NAME)));
assertThat(config).isEqualTo(mSoftApModeConfigCaptor.getValue().getSoftApConfiguration());
mStateMachineSoftApCallback.onStateChanged(WIFI_AP_STATE_ENABLED, 0);
mWifiServiceImpl.updateInterfaceIpState(WIFI_IFACE_NAME, IFACE_IP_MODE_TETHERED);
mLooper.dispatchAll();
assertEquals(WIFI_AP_STATE_ENABLED, mWifiServiceImpl.getWifiApEnabledState());
reset(mActiveModeWarden);
// Start another session without a stop, that should fail.
mLooper.startAutoDispatch();
assertFalse(mWifiServiceImpl.startTetheredHotspot(config, TEST_PACKAGE_NAME));
mLooper.stopAutoDispatchAndIgnoreExceptions();
verifyNoMoreInteractions(mActiveModeWarden);
}
/**
* Only start LocalOnlyHotspot if we are not tethering.
*/
@Test
public void testHotspotDoesNotStartWhenAlreadyTethering() throws Exception {
WifiConfiguration config = createValidWifiApConfiguration();
mLooper.startAutoDispatch();
assertTrue(mWifiServiceImpl.startSoftAp(config, TEST_PACKAGE_NAME));
mStateMachineSoftApCallback.onStateChanged(WIFI_AP_STATE_ENABLED, 0);
mWifiServiceImpl.updateInterfaceIpState(WIFI_IFACE_NAME, IFACE_IP_MODE_TETHERED);
mLooper.stopAutoDispatchAndIgnoreExceptions();
when(mWifiPermissionsUtil.isLocationModeEnabled()).thenReturn(true);
when(mFrameworkFacade.isAppForeground(any(), anyInt())).thenReturn(true);
mLooper.dispatchAll();
int returnCode = mWifiServiceImpl.startLocalOnlyHotspot(
mLohsCallback, TEST_PACKAGE_NAME, TEST_FEATURE_ID, null);
assertEquals(ERROR_INCOMPATIBLE_MODE, returnCode);
}
/**
* Only start LocalOnlyHotspot if admin setting does not disallow tethering.
*/
@Test
public void testHotspotDoesNotStartWhenTetheringDisallowed() throws Exception {
when(mWifiPermissionsUtil.isLocationModeEnabled()).thenReturn(true);
when(mFrameworkFacade.isAppForeground(any(), anyInt())).thenReturn(true);
when(mUserManager.hasUserRestrictionForUser(
eq(UserManager.DISALLOW_CONFIG_TETHERING), any()))
.thenReturn(true);
int returnCode = mWifiServiceImpl.startLocalOnlyHotspot(
mLohsCallback, TEST_PACKAGE_NAME, TEST_FEATURE_ID, null);
assertEquals(ERROR_TETHERING_DISALLOWED, returnCode);
}
/**
* Verify that callers can only have one registered LOHS request.
*/
@Test(expected = IllegalStateException.class)
public void testStartLocalOnlyHotspotThrowsExceptionWhenCallerAlreadyRegistered() {
mLooper.startAutoDispatch();
registerLOHSRequestFull();
stopAutoDispatchWithDispatchAllBeforeStopAndIgnoreExceptions(mLooper);
// now do the second request that will fail
mWifiServiceImpl.startLocalOnlyHotspot(
mLohsCallback, TEST_PACKAGE_NAME, TEST_FEATURE_ID, null);
}
/**
* Verify that the call to stopLocalOnlyHotspot does not do anything when there aren't any
* registered callers.
*/
@Test
public void testStopLocalOnlyHotspotDoesNothingWithoutRegisteredRequests() throws Exception {
// allow test to proceed without a permission check failure
mWifiServiceImpl.stopLocalOnlyHotspot();
mLooper.dispatchAll();
// there is nothing registered, so this shouldn't do anything
verify(mActiveModeWarden, never()).stopSoftAp(anyInt());
}
/**
* Verify that the call to stopLocalOnlyHotspot does not do anything when one caller unregisters
* but there is still an active request
*/
@Test
public void testStopLocalOnlyHotspotDoesNothingWithRemainingRequest() throws Exception {
mLooper.startAutoDispatch();
// register a request that will remain after the stopLOHS call
mWifiServiceImpl.registerLOHSForTest(mPid, mRequestInfo);
setupLocalOnlyHotspot();
stopAutoDispatchWithDispatchAllBeforeStopAndIgnoreExceptions(mLooper);
// Since we are calling with the same pid, the second register call will be removed
mWifiServiceImpl.stopLocalOnlyHotspot();
mLooper.dispatchAll();
// there is still a valid registered request - do not tear down LOHS
verify(mActiveModeWarden, never()).stopSoftAp(anyInt());
}
/**
* Verify that the call to stopLocalOnlyHotspot sends a message to WifiController to stop
* the softAp when there is one registered caller when that caller is removed.
*/
@Test
public void testStopLocalOnlyHotspotTriggersStopWithOneRegisteredRequest() throws Exception {
setupLocalOnlyHotspot();
verify(mActiveModeWarden).startSoftAp(any(), any());
mWifiServiceImpl.stopLocalOnlyHotspot();
mLooper.dispatchAll();
// No permission check required for change_wifi_state.
verify(mContext, never()).enforceCallingOrSelfPermission(
eq("android.Manifest.permission.CHANGE_WIFI_STATE"), anyString());
// there is was only one request registered, we should tear down LOHS
verify(mActiveModeWarden).stopSoftAp(WifiManager.IFACE_IP_MODE_LOCAL_ONLY);
}
/**
* Verify that by default startLocalOnlyHotspot starts access point at 2 GHz.
*/
@Test
public void testStartLocalOnlyHotspotAt2Ghz() {
SoftApConfiguration lohsConfig = createValidSoftApConfiguration();
when(mWifiApConfigStore.generateLocalOnlyHotspotConfig(
eq(mContext), eq(SoftApConfiguration.BAND_2GHZ), eq(null))).thenReturn(lohsConfig);
mLooper.startAutoDispatch();
registerLOHSRequestFull();
stopAutoDispatchWithDispatchAllBeforeStopAndIgnoreExceptions(mLooper);
verify(mWifiApConfigStore).generateLocalOnlyHotspotConfig(
eq(mContext), eq(SoftApConfiguration.BAND_2GHZ), eq(null));
verifyLohsBand(SoftApConfiguration.BAND_2GHZ);
}
/**
* Verify that startLocalOnlyHotspot will start access point at 6 GHz if properly configured
* and if feasible, even if the 5GHz is enabled.
*/
@Test
public void testStartLocalOnlyHotspotAt6Ghz() {
when(mResources.getBoolean(
eq(R.bool.config_wifi_local_only_hotspot_5ghz)))
.thenReturn(true);
when(mResources.getBoolean(
eq(R.bool.config_wifiLocalOnlyHotspot6ghz)))
.thenReturn(true);
setup5GhzSupported();
setup6GhzSupported();
when(mResources.getBoolean(
eq(R.bool.config_wifiSoftap6ghzSupported)))
.thenReturn(true);
when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)).thenReturn(true);
SoftApConfiguration lohsConfig = createValidSoftApConfiguration();
SoftApConfiguration customizedConfig = new SoftApConfiguration.Builder(lohsConfig)
.setBand(SoftApConfiguration.BAND_6GHZ).build();
when(mWifiApConfigStore.generateLocalOnlyHotspotConfig(
eq(mContext), eq(SoftApConfiguration.BAND_6GHZ), eq(null)))
.thenReturn(customizedConfig);
mLooper.startAutoDispatch();
registerLOHSRequestFull();
stopAutoDispatchWithDispatchAllBeforeStopAndIgnoreExceptions(mLooper);
verify(mWifiApConfigStore).generateLocalOnlyHotspotConfig(
eq(mContext), eq(SoftApConfiguration.BAND_6GHZ), eq(null));
verifyLohsBand(SoftApConfiguration.BAND_6GHZ);
}
/**
* Verify that startLocalOnlyHotspot will start access point at 5 GHz if both 5GHz and 6GHz
* are enabled, but SoftAp is not supported for 6GHz.
*/
@Test
public void testStartLocalOnlyHotspotAt5Ghz() {
when(mResources.getBoolean(
eq(R.bool.config_wifi_local_only_hotspot_5ghz)))
.thenReturn(true);
setup5GhzSupported();
setup6GhzSupported();
when(mResources.getBoolean(
eq(R.bool.config_wifiSoftap6ghzSupported)))
.thenReturn(false);
when(mResources.getBoolean(
eq(R.bool.config_wifiLocalOnlyHotspot6ghz)))
.thenReturn(true);
when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)).thenReturn(true);
SoftApConfiguration lohsConfig = createValidSoftApConfiguration();
SoftApConfiguration customizedConfig = new SoftApConfiguration.Builder(lohsConfig)
.setBand(SoftApConfiguration.BAND_5GHZ).build();
when(mWifiApConfigStore.generateLocalOnlyHotspotConfig(
eq(mContext), eq(SoftApConfiguration.BAND_5GHZ), eq(null)))
.thenReturn(customizedConfig);
mLooper.startAutoDispatch();
registerLOHSRequestFull();
stopAutoDispatchWithDispatchAllBeforeStopAndIgnoreExceptions(mLooper);
verify(mWifiApConfigStore).generateLocalOnlyHotspotConfig(
eq(mContext), eq(SoftApConfiguration.BAND_5GHZ), eq(null));
verifyLohsBand(SoftApConfiguration.BAND_5GHZ);
}
private void verifyLohsBand(int expectedBand) {
verify(mActiveModeWarden).startSoftAp(mSoftApModeConfigCaptor.capture(),
eq(TEST_SETTINGS_WORKSOURCE));
final SoftApConfiguration configuration =
mSoftApModeConfigCaptor.getValue().getSoftApConfiguration();
assertNotNull(configuration);
assertEquals(expectedBand, configuration.getBand());
}
private static class FakeLohsCallback extends ILocalOnlyHotspotCallback.Stub {
boolean mIsStarted = false;
SoftApConfiguration mSoftApConfig = null;
@Override
public void onHotspotStarted(SoftApConfiguration softApConfig) {
mIsStarted = true;
this.mSoftApConfig = softApConfig;
}
@Override
public void onHotspotStopped() {
mIsStarted = false;
mSoftApConfig = null;
}
@Override
public void onHotspotFailed(int i) {
mIsStarted = false;
mSoftApConfig = null;
}
}
private void setupForCustomLohs() {
setupLohsPermissions();
when(mContext.checkPermission(eq(Manifest.permission.NETWORK_SETUP_WIZARD),
anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED);
setupWardenForCustomLohs();
}
private void setupWardenForCustomLohs() {
doAnswer(invocation -> {
changeLohsState(WIFI_AP_STATE_ENABLED, WIFI_AP_STATE_DISABLED, HOTSPOT_NO_ERROR);
mWifiServiceImpl.updateInterfaceIpState(mLohsInterfaceName, IFACE_IP_MODE_LOCAL_ONLY);
return null;
}).when(mActiveModeWarden).startSoftAp(any(), any());
}
@Test(expected = SecurityException.class)
public void testCustomLohs_FailsWithoutPermission() {
SoftApConfiguration customConfig = new SoftApConfiguration.Builder()
.setSsid("customConfig")
.build();
// set up basic permissions, but not NETWORK_SETUP_WIZARD
setupLohsPermissions();
setupWardenForCustomLohs();
mWifiServiceImpl.startLocalOnlyHotspot(mLohsCallback, TEST_PACKAGE_NAME, TEST_FEATURE_ID,
customConfig);
}
private static void nopDeathCallback(LocalOnlyHotspotRequestInfo requestor) {
}
@Test
public void testCustomLohs_ExclusiveAfterShared() {
mLooper.startAutoDispatch();
FakeLohsCallback sharedCallback = new FakeLohsCallback();
FakeLohsCallback exclusiveCallback = new FakeLohsCallback();
SoftApConfiguration exclusiveConfig = new SoftApConfiguration.Builder()
.setSsid("customSsid")
.build();
setupForCustomLohs();
mWifiServiceImpl.registerLOHSForTest(mPid, new LocalOnlyHotspotRequestInfo(
new WorkSource(), sharedCallback, WifiServiceImplTest::nopDeathCallback, null));
assertThat(mWifiServiceImpl.startLocalOnlyHotspot(exclusiveCallback, TEST_PACKAGE_NAME,
TEST_FEATURE_ID, exclusiveConfig)).isEqualTo(ERROR_GENERIC);
stopAutoDispatchWithDispatchAllBeforeStopAndIgnoreExceptions(mLooper);
assertThat(sharedCallback.mIsStarted).isTrue();
assertThat(exclusiveCallback.mIsStarted).isFalse();
}
@Test
public void testCustomLohs_ExclusiveBeforeShared() {
mLooper.startAutoDispatch();
FakeLohsCallback sharedCallback = new FakeLohsCallback();
FakeLohsCallback exclusiveCallback = new FakeLohsCallback();
SoftApConfiguration exclusiveConfig = new SoftApConfiguration.Builder()
.setSsid("customSsid")
.build();
setupForCustomLohs();
mWifiServiceImpl.registerLOHSForTest(mPid, new LocalOnlyHotspotRequestInfo(
new WorkSource(), exclusiveCallback, WifiServiceImplTest::nopDeathCallback,
exclusiveConfig));
stopAutoDispatchWithDispatchAllBeforeStopAndIgnoreExceptions(mLooper);
assertThat(mWifiServiceImpl.startLocalOnlyHotspot(sharedCallback, TEST_PACKAGE_NAME,
TEST_FEATURE_ID, null)).isEqualTo(ERROR_GENERIC);
assertThat(exclusiveCallback.mIsStarted).isTrue();
assertThat(sharedCallback.mIsStarted).isFalse();
}
@Test
public void testCustomLohs_Wpa2() {
SoftApConfiguration config = new SoftApConfiguration.Builder()
.setSsid("customSsid")
.setPassphrase("passphrase", SoftApConfiguration.SECURITY_TYPE_WPA2_PSK)
.build();
when(mWifiApConfigStore.generateLocalOnlyHotspotConfig(
eq(mContext), eq(SoftApConfiguration.BAND_2GHZ), eq(config))).thenReturn(config);
FakeLohsCallback callback = new FakeLohsCallback();
mLooper.startAutoDispatch();
setupForCustomLohs();
assertThat(
mWifiServiceImpl.startLocalOnlyHotspot(callback, TEST_PACKAGE_NAME, TEST_FEATURE_ID,
config)).isEqualTo(REQUEST_REGISTERED);
stopAutoDispatchWithDispatchAllBeforeStopAndIgnoreExceptions(mLooper);
verify(mWifiApConfigStore).generateLocalOnlyHotspotConfig(
eq(mContext), eq(SoftApConfiguration.BAND_2GHZ), eq(config));
// Use app's worksouce.
verify(mActiveModeWarden).startSoftAp(any(),
eq(new WorkSource(Binder.getCallingUid(), TEST_PACKAGE_NAME)));
assertThat(callback.mIsStarted).isTrue();
assertThat(callback.mSoftApConfig.getSsid()).isEqualTo("customSsid");
assertThat(callback.mSoftApConfig.getSecurityType())
.isEqualTo(SoftApConfiguration.SECURITY_TYPE_WPA2_PSK);
assertThat(callback.mSoftApConfig.getPassphrase()).isEqualTo("passphrase");
}
@Test
public void testCustomLohs_Open() {
SoftApConfiguration config = new SoftApConfiguration.Builder()
.setSsid("customSsid")
.build();
when(mWifiApConfigStore.generateLocalOnlyHotspotConfig(
eq(mContext), eq(SoftApConfiguration.BAND_2GHZ), eq(config))).thenReturn(config);
FakeLohsCallback callback = new FakeLohsCallback();
mLooper.startAutoDispatch();
setupForCustomLohs();
assertThat(
mWifiServiceImpl.startLocalOnlyHotspot(callback, TEST_PACKAGE_NAME, TEST_FEATURE_ID,
config)).isEqualTo(REQUEST_REGISTERED);
stopAutoDispatchWithDispatchAllBeforeStopAndIgnoreExceptions(mLooper);
verify(mWifiApConfigStore).generateLocalOnlyHotspotConfig(
eq(mContext), eq(SoftApConfiguration.BAND_2GHZ), eq(config));
// Use app's worksouce.
verify(mActiveModeWarden).startSoftAp(any(),
eq(new WorkSource(Binder.getCallingUid(), TEST_PACKAGE_NAME)));
assertThat(callback.mIsStarted).isTrue();
assertThat(callback.mSoftApConfig.getSsid()).isEqualTo("customSsid");
assertThat(callback.mSoftApConfig.getSecurityType())
.isEqualTo(SoftApConfiguration.SECURITY_TYPE_OPEN);
assertThat(callback.mSoftApConfig.getPassphrase()).isNull();
}
@Test
public void testCustomLohs_GeneratesSsidIfAbsent() {
SoftApConfiguration lohsConfig = createValidSoftApConfiguration();
SoftApConfiguration customizedConfig = new SoftApConfiguration.Builder()
.setPassphrase("passphrase", SoftApConfiguration.SECURITY_TYPE_WPA2_PSK)
.build();
when(mWifiApConfigStore.generateLocalOnlyHotspotConfig(
eq(mContext), eq(SoftApConfiguration.BAND_2GHZ), eq(customizedConfig)))
.thenReturn(lohsConfig);
mLooper.startAutoDispatch();
FakeLohsCallback callback = new FakeLohsCallback();
setupForCustomLohs();
assertThat(
mWifiServiceImpl.startLocalOnlyHotspot(callback, TEST_PACKAGE_NAME, TEST_FEATURE_ID,
customizedConfig)).isEqualTo(REQUEST_REGISTERED);
stopAutoDispatchWithDispatchAllBeforeStopAndIgnoreExceptions(mLooper);
verify(mWifiApConfigStore).generateLocalOnlyHotspotConfig(
eq(mContext), eq(SoftApConfiguration.BAND_2GHZ), eq(customizedConfig));
// Use app's worksouce.
verify(mActiveModeWarden).startSoftAp(any(),
eq(new WorkSource(Binder.getCallingUid(), TEST_PACKAGE_NAME)));
assertThat(callback.mIsStarted).isTrue();
assertThat(callback.mSoftApConfig.getSsid()).isNotEmpty();
}
@Test
public void testCustomLohs_ForwardsBssid() {
mLooper.startAutoDispatch();
SoftApConfiguration lohsConfig = createValidSoftApConfiguration();
SoftApConfiguration customizedConfig = new SoftApConfiguration.Builder(lohsConfig)
.setBssid(MacAddress.fromString("aa:bb:cc:dd:ee:ff"))
.build();
when(mWifiApConfigStore.generateLocalOnlyHotspotConfig(
eq(mContext), eq(SoftApConfiguration.BAND_2GHZ), eq(customizedConfig)))
.thenReturn(customizedConfig);
FakeLohsCallback callback = new FakeLohsCallback();
setupForCustomLohs();
assertThat(
mWifiServiceImpl.startLocalOnlyHotspot(callback, TEST_PACKAGE_NAME, TEST_FEATURE_ID,
customizedConfig)).isEqualTo(REQUEST_REGISTERED);
stopAutoDispatchWithDispatchAllBeforeStopAndIgnoreExceptions(mLooper);
// Use app's worksouce.
verify(mWifiApConfigStore).generateLocalOnlyHotspotConfig(
eq(mContext), eq(SoftApConfiguration.BAND_2GHZ), eq(customizedConfig));
verify(mActiveModeWarden).startSoftAp(any(),
eq(new WorkSource(Binder.getCallingUid(), TEST_PACKAGE_NAME)));
assertThat(callback.mIsStarted).isTrue();
assertThat(callback.mSoftApConfig.getBssid().toString())
.ignoringCase().isEqualTo("aa:bb:cc:dd:ee:ff");
}
/**
* Verify that WifiServiceImpl does not send the stop ap message if there were no
* pending LOHS requests upon a binder death callback.
*/
@Test
public void testServiceImplNotCalledWhenBinderDeathTriggeredNoRequests() {
LocalOnlyRequestorCallback binderDeathCallback =
mWifiServiceImpl.new LocalOnlyRequestorCallback();
binderDeathCallback.onLocalOnlyHotspotRequestorDeath(mRequestInfo);
verify(mActiveModeWarden, never()).stopSoftAp(WifiManager.IFACE_IP_MODE_LOCAL_ONLY);
}
/**
* Verify that WifiServiceImpl does not send the stop ap message if there are remaining
* registered LOHS requests upon a binder death callback. Additionally verify that softap mode
* will be stopped if that remaining request is removed (to verify the binder death properly
* cleared the requestor that died).
*/
@Test
public void testServiceImplNotCalledWhenBinderDeathTriggeredWithRequests() throws Exception {
mLooper.startAutoDispatch();
LocalOnlyRequestorCallback binderDeathCallback =
mWifiServiceImpl.new LocalOnlyRequestorCallback();
// registering a request directly from the test will not trigger a message to start
// softap mode
mWifiServiceImpl.registerLOHSForTest(mPid, mRequestInfo);
setupLocalOnlyHotspot();
binderDeathCallback.onLocalOnlyHotspotRequestorDeath(mRequestInfo);
verify(mActiveModeWarden, never()).stopSoftAp(anyInt());
reset(mActiveModeWarden);
// now stop as the second request and confirm CMD_SET_AP will be sent to make sure binder
// death requestor was removed
mWifiServiceImpl.stopLocalOnlyHotspot();
verify(mActiveModeWarden).stopSoftAp(WifiManager.IFACE_IP_MODE_LOCAL_ONLY);
stopAutoDispatchWithDispatchAllBeforeStopAndIgnoreExceptions(mLooper);
}
/**
* Verify that a call to registerSoftApCallback throws a SecurityException if the caller does
* not have neither NETWORK_SETTINGS nor MAINLINE_NETWORK_STACK permission.
*/
@Test(expected = SecurityException.class)
public void registerSoftApCallbackThrowsSecurityExceptionOnMissingPermissions() {
when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_DENIED);
when(mContext.checkPermission(eq(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK),
anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_DENIED);
when(mWifiPermissionsUtil.checkConfigOverridePermission(anyInt())).thenReturn(false);
mWifiServiceImpl.registerSoftApCallback(mClientSoftApCallback);
}
/**
* Verify that a call to registerSoftApCallback throws an IllegalArgumentException if the
* parameters are not provided.
*/
@Test
public void registerSoftApCallbackThrowsIllegalArgumentExceptionOnInvalidArguments() {
try {
mWifiServiceImpl.registerSoftApCallback(null);
fail("expected IllegalArgumentException");
} catch (IllegalArgumentException expected) {
}
}
/**
* Verify that a call to unregisterSoftApCallback throws a SecurityException if the caller does
* not have neither NETWORK_SETTINGS nor MAINLINE_NETWORK_STACK permission.
*/
@Test(expected = SecurityException.class)
public void unregisterSoftApCallbackThrowsSecurityExceptionOnMissingPermissions() {
when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_DENIED);
when(mContext.checkPermission(eq(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK),
anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_DENIED);
when(mWifiPermissionsUtil.checkConfigOverridePermission(anyInt())).thenReturn(false);
mWifiServiceImpl.unregisterSoftApCallback(mClientSoftApCallback);
}
/**
* Verifies that we handle softap callback registration failure if we encounter an exception
* while linking to death.
*/
@Test
public void registerSoftApCallbackFailureOnLinkToDeath() throws Exception {
doThrow(new RemoteException())
.when(mAppBinder).linkToDeath(any(IBinder.DeathRecipient.class), anyInt());
mWifiServiceImpl.registerSoftApCallback(mClientSoftApCallback);
mLooper.dispatchAll();
verify(mClientSoftApCallback, never()).onStateChanged(WIFI_AP_STATE_DISABLED, 0);
verify(mClientSoftApCallback, never()).onConnectedClientsOrInfoChanged(
any(), any(), anyBoolean(), anyBoolean());
verify(mClientSoftApCallback, never()).onCapabilityChanged(any());
}
/**
* Registers a soft AP callback, then verifies that the current soft AP state and num clients
* are sent to caller immediately after callback is registered.
*/
private void registerSoftApCallbackAndVerify(ISoftApCallback callback) throws Exception {
mWifiServiceImpl.registerSoftApCallback(callback);
mLooper.dispatchAll();
verify(callback).onStateChanged(WIFI_AP_STATE_DISABLED, 0);
verify(callback).onConnectedClientsOrInfoChanged(new HashMap<String, SoftApInfo>(),
new HashMap<String, List<WifiClient>>(), false, true);
verify(callback).onCapabilityChanged(ApConfigUtil.updateCapabilityFromResource(mContext));
// Don't need to invoke callback when register.
verify(callback, never()).onBlockedClientConnecting(any(), anyInt());
}
/**
* Verify that unregisterSoftApCallback removes callback from registered callbacks list
*/
@Test
public void unregisterSoftApCallbackRemovesCallback() throws Exception {
registerSoftApCallbackAndVerify(mClientSoftApCallback);
mWifiServiceImpl.unregisterSoftApCallback(mClientSoftApCallback);
mLooper.dispatchAll();
reset(mClientSoftApCallback);
mStateMachineSoftApCallback.onConnectedClientsOrInfoChanged(
mTestSoftApInfos, mTestSoftApClients, false);
mLooper.dispatchAll();
verify(mClientSoftApCallback, never()).onConnectedClientsOrInfoChanged(
any(), any(), anyBoolean(), anyBoolean());
}
/**
* Verify that unregisterSoftApCallback is no-op if callback not registered.
*/
@Test
public void unregisterSoftApCallbackDoesNotRemoveCallbackIfCallbackNotMatching()
throws Exception {
registerSoftApCallbackAndVerify(mClientSoftApCallback);
mWifiServiceImpl.unregisterSoftApCallback(mAnotherSoftApCallback);
mLooper.dispatchAll();
mStateMachineSoftApCallback.onConnectedClientsOrInfoChanged(
mTestSoftApInfos, mTestSoftApClients, false);
mLooper.dispatchAll();
verify(mClientSoftApCallback).onConnectedClientsOrInfoChanged(
eq(mTestSoftApInfos), eq(mTestSoftApClients), eq(false), eq(false));
}
/**
* Registers two callbacks, remove one then verify the right callback is being called on events.
*/
@Test
public void correctCallbackIsCalledAfterAddingTwoCallbacksAndRemovingOne() throws Exception {
WifiClient testWifiClient = new WifiClient(MacAddress.fromString("22:33:44:55:66:77"),
WIFI_IFACE_NAME2);
mWifiServiceImpl.registerSoftApCallback(mClientSoftApCallback);
mLooper.dispatchAll();
reset(mClientSoftApCallback);
when(mClientSoftApCallback.asBinder()).thenReturn(mAppBinder);
// Change state from default before registering the second callback
mStateMachineSoftApCallback.onStateChanged(WIFI_AP_STATE_ENABLED, 0);
mStateMachineSoftApCallback.onConnectedClientsOrInfoChanged(
mTestSoftApInfos, mTestSoftApClients, false);
mStateMachineSoftApCallback.onBlockedClientConnecting(testWifiClient, 0);
// Register another callback and verify the new state is returned in the immediate callback
mWifiServiceImpl.registerSoftApCallback(mAnotherSoftApCallback);
mLooper.dispatchAll();
verify(mAnotherSoftApCallback).onStateChanged(WIFI_AP_STATE_ENABLED, 0);
verify(mAnotherSoftApCallback).onConnectedClientsOrInfoChanged(
eq(mTestSoftApInfos), eq(mTestSoftApClients), eq(false), eq(true));
// Verify only first callback will receive onBlockedClientConnecting since it call after
// first callback register but before another callback register.
verify(mClientSoftApCallback).onBlockedClientConnecting(testWifiClient, 0);
verify(mAnotherSoftApCallback, never()).onBlockedClientConnecting(testWifiClient, 0);
// unregister the fisrt callback
mWifiServiceImpl.unregisterSoftApCallback(mClientSoftApCallback);
mLooper.dispatchAll();
// Update soft AP state and verify the remaining callback receives the event
mStateMachineSoftApCallback.onStateChanged(WIFI_AP_STATE_FAILED,
SAP_START_FAILURE_NO_CHANNEL);
mLooper.dispatchAll();
verify(mClientSoftApCallback, never()).onStateChanged(WIFI_AP_STATE_FAILED,
SAP_START_FAILURE_NO_CHANNEL);
verify(mAnotherSoftApCallback).onStateChanged(WIFI_AP_STATE_FAILED,
SAP_START_FAILURE_NO_CHANNEL);
}
/**
* Verify that wifi service registers for callers BinderDeath event
*/
@Test
public void registersForBinderDeathOnRegisterSoftApCallback() throws Exception {
registerSoftApCallbackAndVerify(mClientSoftApCallback);
verify(mAppBinder).linkToDeath(any(IBinder.DeathRecipient.class), anyInt());
}
/**
* Verify that we un-register the soft AP callback on receiving BinderDied event.
*/
@Test
public void unregistersSoftApCallbackOnBinderDied() throws Exception {
ArgumentCaptor<IBinder.DeathRecipient> drCaptor =
ArgumentCaptor.forClass(IBinder.DeathRecipient.class);
registerSoftApCallbackAndVerify(mClientSoftApCallback);
verify(mAppBinder).linkToDeath(drCaptor.capture(), anyInt());
drCaptor.getValue().binderDied();
mLooper.dispatchAll();
reset(mClientSoftApCallback);
// Verify callback is removed from the list as well
Map<String, List<WifiClient>> mTestSoftApClients = mock(Map.class);
Map<String, SoftApInfo> mTestSoftApInfos = mock(Map.class);
mStateMachineSoftApCallback.onConnectedClientsOrInfoChanged(
mTestSoftApInfos, mTestSoftApClients, false);
mLooper.dispatchAll();
verify(mClientSoftApCallback, never()).onConnectedClientsOrInfoChanged(
any(), any(), anyBoolean(), anyBoolean());
}
/**
* Verify that soft AP callback is called on NumClientsChanged event
*/
@Test
public void callsRegisteredCallbacksOnConnectedClientsChangedEvent() throws Exception {
registerSoftApCallbackAndVerify(mClientSoftApCallback);
mStateMachineSoftApCallback.onConnectedClientsOrInfoChanged(
mTestSoftApInfos, mTestSoftApClients, false);
mLooper.dispatchAll();
verify(mClientSoftApCallback).onConnectedClientsOrInfoChanged(
eq(mTestSoftApInfos), eq(mTestSoftApClients), eq(false), eq(false));
}
/**
* Verify that soft AP callback is called on SoftApStateChanged event
*/
@Test
public void callsRegisteredCallbacksOnSoftApStateChangedEvent() throws Exception {
registerSoftApCallbackAndVerify(mClientSoftApCallback);
mStateMachineSoftApCallback.onStateChanged(WIFI_AP_STATE_ENABLED, 0);
mLooper.dispatchAll();
verify(mClientSoftApCallback).onStateChanged(WIFI_AP_STATE_ENABLED, 0);
}
/**
* Verify that mSoftApState and mSoftApNumClients in WifiServiceImpl are being updated on soft
* Ap events, even when no callbacks are registered.
*/
@Test
public void updatesSoftApStateAndConnectedClientsOnSoftApEvents() throws Exception {
WifiClient testWifiClient = new WifiClient(MacAddress.fromString("22:33:44:55:66:77"),
WIFI_IFACE_NAME2);
mStateMachineSoftApCallback.onStateChanged(WIFI_AP_STATE_ENABLED, 0);
mStateMachineSoftApCallback.onConnectedClientsOrInfoChanged(
mTestSoftApInfos, mTestSoftApClients, false);
mStateMachineSoftApCallback.onBlockedClientConnecting(testWifiClient, 0);
// Register callback after num clients and soft AP are changed.
mWifiServiceImpl.registerSoftApCallback(mClientSoftApCallback);
mLooper.dispatchAll();
verify(mClientSoftApCallback).onStateChanged(WIFI_AP_STATE_ENABLED, 0);
verify(mClientSoftApCallback).onConnectedClientsOrInfoChanged(
eq(mTestSoftApInfos), eq(mTestSoftApClients), eq(false), eq(true));
// Don't need to invoke callback when register.
verify(mClientSoftApCallback, never()).onBlockedClientConnecting(any(), anyInt());
}
private class IntentFilterMatcher implements ArgumentMatcher<IntentFilter> {
@Override
public boolean matches(IntentFilter filter) {
return filter.hasAction(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
}
}
/**
* Verify that onFailed is called for registered LOHS callers on SAP_START_FAILURE_GENERAL.
*/
@Test
public void testRegisteredCallbacksTriggeredOnSoftApFailureGeneric() throws Exception {
when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false);
mWifiServiceImpl.checkAndStartWifi();
mLooper.dispatchAll();
verifyApRegistration();
registerLOHSRequestFull();
changeLohsState(WIFI_AP_STATE_FAILED, WIFI_AP_STATE_DISABLED, SAP_START_FAILURE_GENERAL);
mLooper.dispatchAll();
verify(mLohsCallback).onHotspotFailed(ERROR_GENERIC);
}
/**
* Verify that onFailed is called for registered LOHS callers on SAP_START_FAILURE_NO_CHANNEL.
*/
@Test
public void testRegisteredCallbacksTriggeredOnSoftApFailureNoChannel() throws Exception {
when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false);
mWifiServiceImpl.checkAndStartWifi();
mLooper.dispatchAll();
verifyApRegistration();
registerLOHSRequestFull();
changeLohsState(WIFI_AP_STATE_FAILED,
WIFI_AP_STATE_DISABLED, SAP_START_FAILURE_NO_CHANNEL);
mLooper.dispatchAll();
verify(mLohsCallback).onHotspotFailed(ERROR_NO_CHANNEL);
}
/**
* Common setup for starting a LOHS.
*/
private void setupLocalOnlyHotspot() throws Exception {
when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false);
mWifiServiceImpl.checkAndStartWifi();
mLooper.dispatchAll();
verifyApRegistration();
registerLOHSRequestFull();
changeLohsState(WIFI_AP_STATE_ENABLED, WIFI_AP_STATE_DISABLED, HOTSPOT_NO_ERROR);
mWifiServiceImpl.updateInterfaceIpState(mLohsInterfaceName, IFACE_IP_MODE_LOCAL_ONLY);
mLooper.dispatchAll();
verify(mLohsCallback).onHotspotStarted(any());
}
/**
* Verify that onStopped is called for registered LOHS callers when a callback is
* received with WIFI_AP_STATE_DISABLING and LOHS was active.
*/
@Test
public void testRegisteredCallbacksTriggeredOnSoftApDisabling() throws Exception {
setupLocalOnlyHotspot();
changeLohsState(WIFI_AP_STATE_DISABLING, WIFI_AP_STATE_ENABLED, HOTSPOT_NO_ERROR);
mLooper.dispatchAll();
verify(mLohsCallback).onHotspotStopped();
}
/**
* Verify that onStopped is called for registered LOHS callers when a callback is
* received with WIFI_AP_STATE_DISABLED and LOHS was enabled.
*/
@Test
public void testRegisteredCallbacksTriggeredOnSoftApDisabled() throws Exception {
setupLocalOnlyHotspot();
changeLohsState(WIFI_AP_STATE_DISABLED, WIFI_AP_STATE_DISABLING, HOTSPOT_NO_ERROR);
mLooper.dispatchAll();
verify(mLohsCallback).onHotspotStopped();
}
/**
* Verify that no callbacks are called for registered LOHS callers when a callback is
* received and the softap started.
*/
@Test
public void testRegisteredCallbacksNotTriggeredOnSoftApStart() throws Exception {
when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false);
mWifiServiceImpl.checkAndStartWifi();
mLooper.dispatchAll();
verifyApRegistration();
registerLOHSRequestFull();
changeLohsState(WIFI_AP_STATE_ENABLED, WIFI_AP_STATE_DISABLED, HOTSPOT_NO_ERROR);
mLooper.dispatchAll();
verifyZeroInteractions(ignoreStubs(mLohsCallback));
}
/**
* Verify that onStopped is called only once for registered LOHS callers when
* callbacks are received with WIFI_AP_STATE_DISABLING and
* WIFI_AP_STATE_DISABLED when LOHS was enabled.
*/
@Test
public void testRegisteredCallbacksTriggeredOnlyOnceWhenSoftApDisabling() throws Exception {
setupLocalOnlyHotspot();
changeLohsState(WIFI_AP_STATE_DISABLING, WIFI_AP_STATE_ENABLED, HOTSPOT_NO_ERROR);
changeLohsState(WIFI_AP_STATE_DISABLED, WIFI_AP_STATE_DISABLING, HOTSPOT_NO_ERROR);
mLooper.dispatchAll();
verify(mLohsCallback).onHotspotStopped();
}
/**
* Verify that onFailed is called only once for registered LOHS callers when
* callbacks are received with WIFI_AP_STATE_FAILED twice.
*/
@Test
public void testRegisteredCallbacksTriggeredOnlyOnceWhenSoftApFailsTwice() throws Exception {
setupLocalOnlyHotspot();
changeLohsState(WIFI_AP_STATE_FAILED, WIFI_AP_STATE_FAILED, ERROR_GENERIC);
changeLohsState(WIFI_AP_STATE_FAILED, WIFI_AP_STATE_FAILED, ERROR_GENERIC);
mLooper.dispatchAll();
verify(mLohsCallback).onHotspotFailed(ERROR_GENERIC);
}
/**
* Verify that onFailed is called for all registered LOHS callers when
* callbacks are received with WIFI_AP_STATE_FAILED.
*/
@Test
public void testAllRegisteredCallbacksTriggeredWhenSoftApFails() throws Exception {
when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false);
mWifiServiceImpl.checkAndStartWifi();
mLooper.dispatchAll();
verifyApRegistration();
// make an additional request for this test
mWifiServiceImpl.registerLOHSForTest(TEST_PID, mRequestInfo);
registerLOHSRequestFull();
changeLohsState(WIFI_AP_STATE_FAILED, WIFI_AP_STATE_FAILED, ERROR_GENERIC);
changeLohsState(WIFI_AP_STATE_FAILED, WIFI_AP_STATE_FAILED, ERROR_GENERIC);
verify(mRequestInfo).sendHotspotFailedMessage(ERROR_GENERIC);
mLooper.dispatchAll();
verify(mLohsCallback).onHotspotFailed(ERROR_GENERIC);
}
/**
* Verify that onStopped is called for all registered LOHS callers when
* callbacks are received with WIFI_AP_STATE_DISABLED when LOHS was
* active.
*/
@Test
public void testAllRegisteredCallbacksTriggeredWhenSoftApStops() throws Exception {
when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false);
mWifiServiceImpl.checkAndStartWifi();
mLooper.dispatchAll();
verifyApRegistration();
mWifiServiceImpl.registerLOHSForTest(TEST_PID, mRequestInfo);
registerLOHSRequestFull();
mWifiServiceImpl.updateInterfaceIpState(WIFI_IFACE_NAME, IFACE_IP_MODE_LOCAL_ONLY);
mLooper.dispatchAll();
verify(mRequestInfo).sendHotspotStartedMessage(any());
verify(mLohsCallback).onHotspotStarted(any());
reset(mRequestInfo);
clearInvocations(mLohsCallback);
changeLohsState(WIFI_AP_STATE_DISABLING, WIFI_AP_STATE_ENABLED, HOTSPOT_NO_ERROR);
changeLohsState(WIFI_AP_STATE_DISABLED, WIFI_AP_STATE_DISABLING, HOTSPOT_NO_ERROR);
verify(mRequestInfo).sendHotspotStoppedMessage();
mLooper.dispatchAll();
verify(mLohsCallback).onHotspotStopped();
}
/**
* Verify that onFailed is called for all registered LOHS callers when
* callbacks are received with WIFI_AP_STATE_DISABLED when LOHS was
* not active.
*/
@Test
public void testAllRegisteredCallbacksTriggeredWhenSoftApStopsLOHSNotActive() throws Exception {
when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false);
mWifiServiceImpl.checkAndStartWifi();
mLooper.dispatchAll();
verifyApRegistration();
mWifiServiceImpl.registerLOHSForTest(TEST_PID, mRequestInfo);
mWifiServiceImpl.registerLOHSForTest(TEST_PID2, mRequestInfo2);
changeLohsState(WIFI_AP_STATE_DISABLING, WIFI_AP_STATE_ENABLED, HOTSPOT_NO_ERROR);
changeLohsState(WIFI_AP_STATE_DISABLED, WIFI_AP_STATE_DISABLING, HOTSPOT_NO_ERROR);
verify(mRequestInfo).sendHotspotFailedMessage(ERROR_GENERIC);
verify(mRequestInfo2).sendHotspotFailedMessage(ERROR_GENERIC);
}
/**
* Verify that if we do not have registered LOHS requestors and we receive an update that LOHS
* is up and ready for use, we tell WifiController to tear it down. This can happen if softap
* mode fails to come up properly and we get an onFailed message for a tethering call and we
* had registered callers for LOHS.
*/
@Test
public void testLOHSReadyWithoutRegisteredRequestsStopsSoftApMode() {
mWifiServiceImpl.updateInterfaceIpState(WIFI_IFACE_NAME, IFACE_IP_MODE_LOCAL_ONLY);
mLooper.dispatchAll();
verify(mActiveModeWarden).stopSoftAp(WifiManager.IFACE_IP_MODE_LOCAL_ONLY);
}
/**
* Verify that all registered LOHS requestors are notified via a HOTSPOT_STARTED message that
* the hotspot is up and ready to use.
*/
@Test
public void testRegisteredLocalOnlyHotspotRequestorsGetOnStartedCallbackWhenReady()
throws Exception {
SoftApConfiguration lohsConfig = createValidSoftApConfiguration();
when(mWifiApConfigStore.generateLocalOnlyHotspotConfig(
eq(mContext), eq(SoftApConfiguration.BAND_2GHZ), eq(null))).thenReturn(lohsConfig);
mLooper.startAutoDispatch();
registerLOHSRequestFull();
stopAutoDispatchWithDispatchAllBeforeStopAndIgnoreExceptions(mLooper);
verify(mWifiApConfigStore).generateLocalOnlyHotspotConfig(
eq(mContext), eq(SoftApConfiguration.BAND_2GHZ), eq(null));
mWifiServiceImpl.registerLOHSForTest(TEST_PID, mRequestInfo);
mWifiServiceImpl.updateInterfaceIpState(WIFI_IFACE_NAME, IFACE_IP_MODE_LOCAL_ONLY);
mLooper.dispatchAll();
verify(mRequestInfo).sendHotspotStartedMessage(any(SoftApConfiguration.class));
mLooper.dispatchAll();
verify(mLohsCallback).onHotspotStarted(notNull());
}
/**
* Verify that if a LOHS is already active, a new call to register a request will trigger the
* onStarted callback.
*/
@Test
public void testRegisterLocalOnlyHotspotRequestAfterAlreadyStartedGetsOnStartedCallback()
throws Exception {
mLooper.startAutoDispatch();
mWifiServiceImpl.registerLOHSForTest(TEST_PID, mRequestInfo);
changeLohsState(WIFI_AP_STATE_ENABLED, WIFI_AP_STATE_DISABLED, HOTSPOT_NO_ERROR);
mWifiServiceImpl.updateInterfaceIpState(WIFI_IFACE_NAME, IFACE_IP_MODE_LOCAL_ONLY);
registerLOHSRequestFull();
stopAutoDispatchWithDispatchAllBeforeStopAndIgnoreExceptions(mLooper);
verify(mLohsCallback).onHotspotStarted(any());
}
/**
* Verify that if a LOHS request is active and we receive an update with an ip mode
* configuration error, callers are notified via the onFailed callback with the generic
* error and are unregistered.
*/
@Test
public void testCallOnFailedLocalOnlyHotspotRequestWhenIpConfigFails() throws Exception {
setupLocalOnlyHotspot();
reset(mActiveModeWarden);
mWifiServiceImpl.updateInterfaceIpState(WIFI_IFACE_NAME, IFACE_IP_MODE_CONFIGURATION_ERROR);
mLooper.dispatchAll();
verify(mLohsCallback).onHotspotFailed(ERROR_GENERIC);
verify(mActiveModeWarden).stopSoftAp(WifiManager.IFACE_IP_MODE_LOCAL_ONLY);
clearInvocations(mLohsCallback);
// send HOTSPOT_FAILED message should only happen once since the requestor should be
// unregistered
mWifiServiceImpl.updateInterfaceIpState(WIFI_IFACE_NAME, IFACE_IP_MODE_CONFIGURATION_ERROR);
mLooper.dispatchAll();
verifyZeroInteractions(ignoreStubs(mLohsCallback));
}
/**
* Verify that softap mode is stopped for tethering if we receive an update with an ip mode
* configuration error.
*/
@Test
public void testStopSoftApWhenIpConfigFails() throws Exception {
mWifiServiceImpl.updateInterfaceIpState(WIFI_IFACE_NAME, IFACE_IP_MODE_TETHERED);
mWifiServiceImpl.updateInterfaceIpState(WIFI_IFACE_NAME, IFACE_IP_MODE_CONFIGURATION_ERROR);
mLooper.dispatchAll();
verify(mActiveModeWarden).stopSoftAp(IFACE_IP_MODE_TETHERED);
}
/**
* Verify that if a LOHS request is active and tethering starts, callers are notified on the
* incompatible mode and are unregistered.
*/
@Test
public void testCallOnFailedLocalOnlyHotspotRequestWhenTetheringStarts() throws Exception {
mLooper.startAutoDispatch();
registerLOHSRequestFull();
mWifiServiceImpl.updateInterfaceIpState(WIFI_IFACE_NAME, IFACE_IP_MODE_LOCAL_ONLY);
mLooper.dispatchAll();
verify(mLohsCallback).onHotspotStarted(any());
clearInvocations(mLohsCallback);
mWifiServiceImpl.updateInterfaceIpState(WIFI_IFACE_NAME, IFACE_IP_MODE_TETHERED);
mLooper.dispatchAll();
verify(mLohsCallback).onHotspotFailed(ERROR_INCOMPATIBLE_MODE);
// sendMessage should only happen once since the requestor should be unregistered
clearInvocations(mLohsCallback);
mWifiServiceImpl.updateInterfaceIpState(WIFI_IFACE_NAME, IFACE_IP_MODE_TETHERED);
verifyZeroInteractions(ignoreStubs(mLohsCallback));
stopAutoDispatchWithDispatchAllBeforeStopAndIgnoreExceptions(mLooper);
}
/**
* Verify that if LOHS is disabled, a new call to register a request will not trigger the
* onStopped callback.
*/
@Test
public void testRegisterLocalOnlyHotspotRequestWhenStoppedDoesNotGetOnStoppedCallback()
throws Exception {
mLooper.startAutoDispatch();
registerLOHSRequestFull();
verifyZeroInteractions(ignoreStubs(mLohsCallback));
stopAutoDispatchWithDispatchAllBeforeStopAndIgnoreExceptions(mLooper);
}
/**
* Verify that if a LOHS was active and then stopped, a new call to register a request will
* not trigger the onStarted callback.
*/
@Test
public void testRegisterLocalOnlyHotspotRequestAfterStoppedNoOnStartedCallback()
throws Exception {
when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false);
mWifiServiceImpl.checkAndStartWifi();
mLooper.dispatchAll();
verifyApRegistration();
// register a request so we don't drop the LOHS interface ip update
mWifiServiceImpl.registerLOHSForTest(TEST_PID, mRequestInfo);
changeLohsState(WIFI_AP_STATE_ENABLED, WIFI_AP_STATE_DISABLED, HOTSPOT_NO_ERROR);
mWifiServiceImpl.updateInterfaceIpState(WIFI_IFACE_NAME, IFACE_IP_MODE_LOCAL_ONLY);
mLooper.dispatchAll();
registerLOHSRequestFull();
mLooper.dispatchAll();
verify(mLohsCallback).onHotspotStarted(any());
clearInvocations(mLohsCallback);
// now stop the hotspot
changeLohsState(WIFI_AP_STATE_DISABLING, WIFI_AP_STATE_ENABLED, HOTSPOT_NO_ERROR);
changeLohsState(WIFI_AP_STATE_DISABLED, WIFI_AP_STATE_DISABLING, HOTSPOT_NO_ERROR);
mLooper.dispatchAll();
verify(mLohsCallback).onHotspotStopped();
clearInvocations(mLohsCallback);
// now register a new caller - they should not get the onStarted callback
ILocalOnlyHotspotCallback callback2 = mock(ILocalOnlyHotspotCallback.class);
when(callback2.asBinder()).thenReturn(mock(IBinder.class));
int result = mWifiServiceImpl.startLocalOnlyHotspot(
callback2, TEST_PACKAGE_NAME, TEST_FEATURE_ID, null);
assertEquals(LocalOnlyHotspotCallback.REQUEST_REGISTERED, result);
mLooper.dispatchAll();
verify(mLohsCallback, never()).onHotspotStarted(any());
}
/**
* Verify that a call to startWatchLocalOnlyHotspot is only allowed from callers with the
* signature only NETWORK_SETTINGS permission.
*
* This test is expecting the permission check to enforce the permission and throw a
* SecurityException for callers without the permission. This exception should be bubbled up to
* the caller of startLocalOnlyHotspot.
*/
@Test(expected = SecurityException.class)
public void testStartWatchLocalOnlyHotspotNotApprovedCaller() {
doThrow(new SecurityException()).when(mContext)
.enforceCallingOrSelfPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
eq("WifiService"));
mWifiServiceImpl.startWatchLocalOnlyHotspot(mLohsCallback);
}
/**
* Verify that the call to startWatchLocalOnlyHotspot throws the UnsupportedOperationException
* when called until the implementation is complete.
*/
@Test(expected = UnsupportedOperationException.class)
public void testStartWatchLocalOnlyHotspotNotSupported() {
mWifiServiceImpl.startWatchLocalOnlyHotspot(mLohsCallback);
}
/**
* Verify that a call to stopWatchLocalOnlyHotspot is only allowed from callers with the
* signature only NETWORK_SETTINGS permission.
*/
@Test(expected = SecurityException.class)
public void testStopWatchLocalOnlyHotspotNotApprovedCaller() {
doThrow(new SecurityException()).when(mContext)
.enforceCallingOrSelfPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
eq("WifiService"));
mWifiServiceImpl.stopWatchLocalOnlyHotspot();
}
/**
* Verify that the call to stopWatchLocalOnlyHotspot throws the UnsupportedOperationException
* until the implementation is complete.
*/
@Test(expected = UnsupportedOperationException.class)
public void testStopWatchLocalOnlyHotspotNotSupported() {
mWifiServiceImpl.stopWatchLocalOnlyHotspot();
}
/**
* Verify that the call to addOrUpdateNetwork for installing Passpoint profile is redirected
* to the Passpoint specific API addOrUpdatePasspointConfiguration.
*/
@Test
public void testAddPasspointProfileViaAddNetwork() throws Exception {
WifiConfiguration config = WifiConfigurationTestUtil.createPasspointNetwork();
config.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TLS);
PackageManager pm = mock(PackageManager.class);
when(mContext.getPackageManager()).thenReturn(pm);
when(pm.getApplicationInfoAsUser(any(), anyInt(), any())).thenReturn(mApplicationInfo);
when(mWifiPermissionsUtil.isTargetSdkLessThan(anyString(),
eq(Build.VERSION_CODES.Q), anyInt())).thenReturn(true);
when(mWifiPermissionsUtil.isTargetSdkLessThan(anyString(),
eq(Build.VERSION_CODES.R), anyInt())).thenReturn(true);
when(mPasspointManager.addOrUpdateProvider(
any(PasspointConfiguration.class), anyInt(), eq(TEST_PACKAGE_NAME), eq(false),
eq(true))).thenReturn(true);
mLooper.startAutoDispatch();
assertEquals(0, WifiConfigurationUtil.removeSecurityTypeFromNetworkId(
mWifiServiceImpl.addOrUpdateNetwork(config, TEST_PACKAGE_NAME)));
mLooper.stopAutoDispatchAndIgnoreExceptions();
verifyCheckChangePermission(TEST_PACKAGE_NAME);
verify(mPasspointManager).addOrUpdateProvider(
any(PasspointConfiguration.class), anyInt(), eq(TEST_PACKAGE_NAME), eq(false),
eq(true));
reset(mPasspointManager);
when(mPasspointManager.addOrUpdateProvider(
any(PasspointConfiguration.class), anyInt(), eq(TEST_PACKAGE_NAME), anyBoolean(),
anyBoolean())).thenReturn(false);
mLooper.startAutoDispatch();
assertEquals(-1, mWifiServiceImpl.addOrUpdateNetwork(config, TEST_PACKAGE_NAME));
mLooper.stopAutoDispatchAndIgnoreExceptions();
verifyCheckChangePermission(TEST_PACKAGE_NAME);
verify(mPasspointManager).addOrUpdateProvider(
any(PasspointConfiguration.class), anyInt(), eq(TEST_PACKAGE_NAME), anyBoolean(),
anyBoolean());
}
/**
* Verify that the call to getAllMatchingPasspointProfilesForScanResults is not redirected to
* specific API getAllMatchingPasspointProfilesForScanResults when the caller doesn't have
* NETWORK_SETTINGS permissions and NETWORK_SETUP_WIZARD.
*/
@Test(expected = SecurityException.class)
public void testGetAllMatchingPasspointProfilesForScanResultsWithoutPermissions() {
mWifiServiceImpl.getAllMatchingPasspointProfilesForScanResults(new ArrayList<>());
}
/**
* Verify that the call to getAllMatchingPasspointProfilesForScanResults is redirected to
* specific API getAllMatchingPasspointProfilesForScanResults when the caller have
* NETWORK_SETTINGS permissions and NETWORK_SETUP_WIZARD.
*/
@Test
public void testGetAllMatchingPasspointProfilesForScanResultsWithPermissions() {
when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED);
mLooper.startAutoDispatch();
mWifiServiceImpl.getAllMatchingPasspointProfilesForScanResults(createScanResultList());
mLooper.stopAutoDispatchAndIgnoreExceptions();
verify(mPasspointManager).getAllMatchingPasspointProfilesForScanResults(any());
}
/**
* Verify that the call to getAllMatchingPasspointProfilesForScanResults is not redirected to
* specific API getAllMatchingPasspointProfilesForScanResults when the caller provider invalid
* ScanResult.
*/
@Test
public void testGetAllMatchingPasspointProfilesForScanResultsWithInvalidScanResult() {
when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED);
mLooper.startAutoDispatch();
mWifiServiceImpl.getAllMatchingPasspointProfilesForScanResults(new ArrayList<>());
mLooper.stopAutoDispatchAndIgnoreExceptions();
verify(mPasspointManager, never()).getAllMatchingPasspointProfilesForScanResults(any());
}
/**
* Verify that the call to getWifiConfigsForPasspointProfiles is not redirected to specific API
* syncGetWifiConfigsForPasspointProfiles when the caller doesn't have NETWORK_SETTINGS
* permissions and NETWORK_SETUP_WIZARD.
*/
@Test(expected = SecurityException.class)
public void testGetWifiConfigsForPasspointProfilesWithoutPermissions() {
mWifiServiceImpl.getWifiConfigsForPasspointProfiles(new ArrayList<>());
}
/**
* Verify that the call to getMatchingOsuProviders is not redirected to specific API
* syncGetMatchingOsuProviders when the caller doesn't have NETWORK_SETTINGS
* permissions and NETWORK_SETUP_WIZARD.
*/
@Test(expected = SecurityException.class)
public void testGetMatchingOsuProvidersWithoutPermissions() {
mWifiServiceImpl.getMatchingOsuProviders(new ArrayList<>());
}
/**
* Verify that the call to getMatchingOsuProviders is redirected to specific API
* syncGetMatchingOsuProviders when the caller have NETWORK_SETTINGS
* permissions and NETWORK_SETUP_WIZARD.
*/
@Test
public void testGetMatchingOsuProvidersWithPermissions() {
when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED);
mLooper.startAutoDispatch();
mWifiServiceImpl.getMatchingOsuProviders(createScanResultList());
mLooper.stopAutoDispatch();
verify(mPasspointManager).getMatchingOsuProviders(any());
}
/**
* Verify that the call to getMatchingOsuProviders is not redirected to specific API
* syncGetMatchingOsuProviders when the caller provider invalid ScanResult
*/
@Test
public void testGetMatchingOsuProvidersWithInvalidScanResult() {
when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED);
mWifiServiceImpl.getMatchingOsuProviders(new ArrayList<>());
mLooper.dispatchAll();
verify(mPasspointManager, never()).getMatchingOsuProviders(any());
}
/**
* Verify that the call to getMatchingPasspointConfigsForOsuProviders is not redirected to
* specific API syncGetMatchingPasspointConfigsForOsuProviders when the caller doesn't have
* NETWORK_SETTINGS permissions and NETWORK_SETUP_WIZARD.
*/
@Test(expected = SecurityException.class)
public void testGetMatchingPasspointConfigsForOsuProvidersWithoutPermissions() {
mWifiServiceImpl.getMatchingPasspointConfigsForOsuProviders(new ArrayList<>());
}
/**
* Verify that the call to startSubscriptionProvisioning is redirected to the Passpoint
* specific API startSubscriptionProvisioning when the caller has the right permissions.
*/
@Test
public void testStartSubscriptionProvisioningWithPermission() throws Exception {
when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED);
when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETUP_WIZARD),
anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED);
mLooper.startAutoDispatch();
mWifiServiceImpl.startSubscriptionProvisioning(mOsuProvider, mProvisioningCallback);
mLooper.stopAutoDispatch();
verify(mClientModeManager).syncStartSubscriptionProvisioning(anyInt(),
eq(mOsuProvider), eq(mProvisioningCallback));
}
/**
* Verify that the call to startSubscriptionProvisioning is not redirected to the Passpoint
* specific API startSubscriptionProvisioning when the caller provides invalid arguments
*/
@Test(expected = IllegalArgumentException.class)
public void testStartSubscriptionProvisioningWithInvalidProvider() throws Exception {
mWifiServiceImpl.startSubscriptionProvisioning(null, mProvisioningCallback);
}
/**
* Verify that the call to startSubscriptionProvisioning is not redirected to the Passpoint
* specific API startSubscriptionProvisioning when the caller provides invalid callback
*/
@Test(expected = IllegalArgumentException.class)
public void testStartSubscriptionProvisioningWithInvalidCallback() throws Exception {
mWifiServiceImpl.startSubscriptionProvisioning(mOsuProvider, null);
}
/**
* Verify that the call to startSubscriptionProvisioning is not redirected to the Passpoint
* specific API startSubscriptionProvisioning when the caller doesn't have NETWORK_SETTINGS
* permissions and NETWORK_SETUP_WIZARD.
*/
@Test(expected = SecurityException.class)
public void testStartSubscriptionProvisioningWithoutPermissions() throws Exception {
when(mContext.checkCallingOrSelfPermission(
eq(android.Manifest.permission.NETWORK_SETTINGS))).thenReturn(
PackageManager.PERMISSION_DENIED);
when(mContext.checkSelfPermission(
eq(android.Manifest.permission.NETWORK_SETUP_WIZARD))).thenReturn(
PackageManager.PERMISSION_DENIED);
mWifiServiceImpl.startSubscriptionProvisioning(mOsuProvider, mProvisioningCallback);
}
/**
* Verify the call to getPasspointConfigurations when the caller doesn't have
* NETWORK_SETTINGS and NETWORK_SETUP_WIZARD permissions.
*/
@Test
public void testGetPasspointConfigurationsWithOutPrivilegedPermissions() {
when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(false);
when(mWifiPermissionsUtil.checkNetworkSetupWizardPermission(anyInt())).thenReturn(false);
mLooper.startAutoDispatch();
mWifiServiceImpl.getPasspointConfigurations(TEST_PACKAGE_NAME);
mLooper.stopAutoDispatchAndIgnoreExceptions();
verify(mPasspointManager).getProviderConfigs(Binder.getCallingUid(), false);
}
/**
* Verify that the call to getPasspointConfigurations when the caller does have
* NETWORK_SETTINGS permission.
*/
@Test
public void testGetPasspointConfigurationsWithPrivilegedPermissions() {
when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(true);
mLooper.startAutoDispatch();
mWifiServiceImpl.getPasspointConfigurations(TEST_PACKAGE_NAME);
mLooper.stopAutoDispatchAndIgnoreExceptions();
verify(mPasspointManager).getProviderConfigs(Binder.getCallingUid(), true);
}
/**
* Verify that GetPasspointConfigurations will redirect calls to {@link PasspointManager}
* and returning the result that's returned from {@link PasspointManager}.
*/
@Test
public void testGetPasspointConfigurations() throws Exception {
when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(true);
// Setup expected configs.
List<PasspointConfiguration> expectedConfigs = new ArrayList<>();
PasspointConfiguration config = new PasspointConfiguration();
HomeSp homeSp = new HomeSp();
homeSp.setFqdn("test.com");
config.setHomeSp(homeSp);
expectedConfigs.add(config);
when(mPasspointManager.getProviderConfigs(anyInt(), anyBoolean()))
.thenReturn(expectedConfigs);
mLooper.startAutoDispatch();
assertEquals(expectedConfigs, mWifiServiceImpl.getPasspointConfigurations(TEST_PACKAGE));
mLooper.stopAutoDispatchAndIgnoreExceptions();
reset(mPasspointManager);
when(mPasspointManager.getProviderConfigs(anyInt(), anyBoolean()))
.thenReturn(new ArrayList<PasspointConfiguration>());
mLooper.startAutoDispatch();
assertTrue(mWifiServiceImpl.getPasspointConfigurations(TEST_PACKAGE).isEmpty());
mLooper.stopAutoDispatchAndIgnoreExceptions();
}
/**
* Verify the call to removePasspointConfigurations when the caller doesn't have
* NETWORK_SETTINGS and NETWORK_CARRIER_PROVISIONING permissions.
*/
@Test
public void testRemovePasspointConfigurationWithOutPrivilegedPermissions() {
when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(false);
when(mWifiPermissionsUtil.checkNetworkCarrierProvisioningPermission(anyInt())).thenReturn(
false);
mLooper.startAutoDispatch();
mWifiServiceImpl.removePasspointConfiguration(TEST_FQDN, TEST_PACKAGE_NAME);
mLooper.stopAutoDispatchAndIgnoreExceptions();
verify(mPasspointManager).removeProvider(Binder.getCallingUid(), false, null,
TEST_FQDN);
}
/**
* Verify the call to removePasspointConfigurations when the caller does have
* NETWORK_CARRIER_PROVISIONING permission.
*/
@Test
public void testRemovePasspointConfigurationWithPrivilegedPermissions() {
when(mWifiPermissionsUtil.checkNetworkCarrierProvisioningPermission(anyInt())).thenReturn(
true);
mLooper.startAutoDispatch();
mWifiServiceImpl.removePasspointConfiguration(TEST_FQDN, TEST_PACKAGE_NAME);
mLooper.stopAutoDispatchAndIgnoreExceptions();
verify(mPasspointManager).removeProvider(Binder.getCallingUid(), true, null,
TEST_FQDN);
}
/**
* Verify that a call to {@link WifiServiceImpl#restoreBackupData(byte[])} is only allowed from
* callers with the signature only NETWORK_SETTINGS permission.
*/
@Test(expected = SecurityException.class)
public void testRestoreBackupDataNotApprovedCaller() {
doThrow(new SecurityException()).when(mContext)
.enforceCallingOrSelfPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
eq("WifiService"));
mWifiServiceImpl.restoreBackupData(null);
verify(mWifiBackupRestore, never()).retrieveConfigurationsFromBackupData(any(byte[].class));
}
/**
* Verify that a call to {@link WifiServiceImpl#restoreSupplicantBackupData(byte[], byte[])} is
* only allowed from callers with the signature only NETWORK_SETTINGS permission.
*/
@Test(expected = SecurityException.class)
public void testRestoreSupplicantBackupDataNotApprovedCaller() {
doThrow(new SecurityException()).when(mContext)
.enforceCallingOrSelfPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
eq("WifiService"));
mWifiServiceImpl.restoreSupplicantBackupData(null, null);
verify(mWifiBackupRestore, never()).retrieveConfigurationsFromSupplicantBackupData(
any(byte[].class), any(byte[].class));
}
/**
* Verify that a call to {@link WifiServiceImpl#retrieveBackupData()} is only allowed from
* callers with the signature only NETWORK_SETTINGS permission.
*/
@Test(expected = SecurityException.class)
public void testRetrieveBackupDataNotApprovedCaller() {
doThrow(new SecurityException()).when(mContext)
.enforceCallingOrSelfPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
eq("WifiService"));
mWifiServiceImpl.retrieveBackupData();
verify(mWifiBackupRestore, never()).retrieveBackupDataFromConfigurations(any(List.class));
}
/**
* Verify that a call to {@link WifiServiceImpl#restoreSoftApBackupData(byte[])}
* is only allowed from callers with the signature only NETWORK_SETTINGS permission.
*/
@Test(expected = SecurityException.class)
public void testRestoreSoftApBackupDataNotApprovedCaller() {
doThrow(new SecurityException()).when(mContext)
.enforceCallingOrSelfPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
eq("WifiService"));
mWifiServiceImpl.restoreSoftApBackupData(null);
verify(mSoftApBackupRestore, never())
.retrieveSoftApConfigurationFromBackupData(any(byte[].class));
}
/**
* Verify that a call to {@link WifiServiceImpl#restoreSoftApBackupData(byte[])}
* will call WifiApConfigStore#upgradeSoftApConfiguration and
* WifiApConfigStore#resetToDefaultForUnsupportedConfig.
*/
@Test
public void testRestoreSoftApBackupData() {
when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED);
InOrder inorder = inOrder(mWifiApConfigStore);
SoftApConfiguration testConfig = new SoftApConfiguration.Builder().setSsid("test").build();
byte[] testData = testConfig.toString().getBytes();
when(mSoftApBackupRestore.retrieveSoftApConfigurationFromBackupData(testData))
.thenReturn(testConfig);
mWifiServiceImpl.restoreSoftApBackupData(testData);
mLooper.dispatchAll();
inorder.verify(mWifiApConfigStore).upgradeSoftApConfiguration(testConfig);
inorder.verify(mWifiApConfigStore).resetToDefaultForUnsupportedConfig(any());
inorder.verify(mWifiApConfigStore).setApConfiguration(any());
}
/**
* Verify that a call to {@link WifiServiceImpl#retrieveSoftApBackupData()} is only allowed from
* callers with the signature only NETWORK_SETTINGS permission.
*/
@Test(expected = SecurityException.class)
public void testRetrieveSoftApBackupDataNotApprovedCaller() {
doThrow(new SecurityException()).when(mContext)
.enforceCallingOrSelfPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
eq("WifiService"));
mWifiServiceImpl.retrieveSoftApBackupData();
verify(mSoftApBackupRestore, never())
.retrieveBackupDataFromSoftApConfiguration(any(SoftApConfiguration.class));
}
class TestWifiVerboseLoggingStatusChangedListener extends
IWifiVerboseLoggingStatusChangedListener.Stub {
public int numStatusChangedCounts;
public boolean lastReceivedValue;
@Override
public void onStatusChanged(boolean enabled) throws RemoteException {
numStatusChangedCounts++;
lastReceivedValue = enabled;
}
}
/**
* Verify that a call to {@link WifiServiceImpl#enableVerboseLogging(int)} is propagated to
* registered {@link IWifiVerboseLoggingStatusChangedListener}. Then, verify that changes are no
* longer propagated when the listener gets unregistered.
*/
@Test
public void testVerboseLoggingListener() throws Exception {
doNothing().when(mContext)
.enforceCallingOrSelfPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
eq("WifiService"));
// Verbose logging is enabled first in the constructor for WifiServiceImpl, so reset
// before invocation.
reset(mClientModeManager);
TestWifiVerboseLoggingStatusChangedListener listener =
new TestWifiVerboseLoggingStatusChangedListener();
mWifiServiceImpl.addWifiVerboseLoggingStatusChangedListener(listener);
mLooper.dispatchAll();
mWifiServiceImpl.enableVerboseLogging(WifiManager.VERBOSE_LOGGING_LEVEL_ENABLED);
verify(mWifiSettingsConfigStore).put(WIFI_VERBOSE_LOGGING_ENABLED, true);
verify(mActiveModeWarden).enableVerboseLogging(anyBoolean());
assertEquals(1, listener.numStatusChangedCounts);
assertTrue(listener.lastReceivedValue);
mWifiServiceImpl.enableVerboseLogging(WifiManager.VERBOSE_LOGGING_LEVEL_DISABLED);
assertEquals(2, listener.numStatusChangedCounts);
assertFalse(listener.lastReceivedValue);
// unregister the callback and verify no more updates happen.
mWifiServiceImpl.removeWifiVerboseLoggingStatusChangedListener(listener);
mLooper.dispatchAll();
mWifiServiceImpl.enableVerboseLogging(WifiManager.VERBOSE_LOGGING_LEVEL_ENABLED);
assertEquals(2, listener.numStatusChangedCounts);
assertFalse(listener.lastReceivedValue);
}
/**
* Verify an exception is thrown for invalid inputs to
* addWifiVerboseLoggingStatusChangedListener and removeWifiVerboseLoggingStatusChangedListener.
*/
@Test
public void testVerboseLoggingListenerInvalidInput() throws Exception {
try {
mWifiServiceImpl.addWifiVerboseLoggingStatusChangedListener(null);
fail("expected IllegalArgumentException in addWifiVerboseLoggingStatusChangedListener");
} catch (IllegalArgumentException e) {
}
try {
mWifiServiceImpl.removeWifiVerboseLoggingStatusChangedListener(null);
fail("expected IllegalArgumentException in "
+ "removeWifiVerboseLoggingStatusChangedListener");
} catch (IllegalArgumentException e) {
}
}
/**
* Verify a SecurityException if the caller doesn't have sufficient permissions.
*/
@Test
public void testVerboseLoggingListenerNoPermission() throws Exception {
doThrow(new SecurityException()).when(mContext)
.enforceCallingOrSelfPermission(eq(ACCESS_WIFI_STATE),
eq("WifiService"));
TestWifiVerboseLoggingStatusChangedListener listener =
new TestWifiVerboseLoggingStatusChangedListener();
try {
mWifiServiceImpl.addWifiVerboseLoggingStatusChangedListener(listener);
fail("expected IllegalArgumentException in addWifiVerboseLoggingStatusChangedListener");
} catch (SecurityException e) {
}
try {
mWifiServiceImpl.removeWifiVerboseLoggingStatusChangedListener(listener);
fail("expected IllegalArgumentException in "
+ "removeWifiVerboseLoggingStatusChangedListener");
} catch (SecurityException e) {
}
}
/**
* Verify that a call to {@link WifiServiceImpl#enableVerboseLogging(int)} is allowed from
* callers with the signature only NETWORK_SETTINGS permission.
*/
@Test
public void testEnableVerboseLoggingWithNetworkSettingsPermission() throws Exception {
doNothing().when(mContext)
.enforceCallingOrSelfPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
eq("WifiService"));
// Verbose logging is enabled first in the constructor for WifiServiceImpl, so reset
// before invocation.
reset(mClientModeManager);
mWifiServiceImpl.enableVerboseLogging(WifiManager.VERBOSE_LOGGING_LEVEL_ENABLED);
verify(mWifiSettingsConfigStore).put(WIFI_VERBOSE_LOGGING_ENABLED, true);
verify(mActiveModeWarden).enableVerboseLogging(anyBoolean());
}
/**
* Verify that setting verbose logging mode to
* {@link WifiManager#VERBOSE_LOGGING_LEVEL_ENABLED_SHOW_KEY)} is allowed from
* callers with the signature only NETWORK_SETTINGS permission.
*/
@Test
public void testEnableShowKeyVerboseLoggingWithNetworkSettingsPermission() throws Exception {
doNothing().when(mContext)
.enforceCallingOrSelfPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
eq("WifiService"));
// Verbose logging is enabled first in the constructor for WifiServiceImpl, so reset
// before invocation.
reset(mClientModeManager);
mWifiServiceImpl.enableVerboseLogging(WifiManager.VERBOSE_LOGGING_LEVEL_ENABLED_SHOW_KEY);
verify(mWifiSettingsConfigStore).put(WIFI_VERBOSE_LOGGING_ENABLED, true);
verify(mActiveModeWarden).enableVerboseLogging(anyBoolean());
verify(mWifiGlobals).setShowKeyVerboseLoggingModeEnabled(eq(true));
// After auto disable show key mode after the countdown
mLooper.moveTimeForward(WifiServiceImpl.AUTO_DISABLE_SHOW_KEY_COUNTDOWN_MILLIS + 1);
mLooper.dispatchAll();
verify(mWifiGlobals).setShowKeyVerboseLoggingModeEnabled(eq(false));
}
/**
* Verify that setting verbose logging level to
* {@link WifiManager#VERBOSE_LOGGING_LEVEL_ENABLED_SHOW_KEY)} is not allowed for
* the user build.
*/
@Test(expected = SecurityException.class)
public void testEnableShowKeyVerboseLoggingNotAllowedForUserBuild() throws Exception {
when(mBuildProperties.isUserBuild()).thenReturn(true);
doNothing().when(mContext)
.enforceCallingOrSelfPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
eq("WifiService"));
// Verbose logging is enabled first in the constructor for WifiServiceImpl, so reset
// before invocation.
reset(mClientModeManager);
mWifiServiceImpl.enableVerboseLogging(WifiManager.VERBOSE_LOGGING_LEVEL_ENABLED_SHOW_KEY);
}
/**
* Verify that a call to {@link WifiServiceImpl#enableVerboseLogging(int)} is not allowed from
* callers without the signature only NETWORK_SETTINGS permission.
*/
@Test(expected = SecurityException.class)
public void testEnableVerboseLoggingWithNoNetworkSettingsPermission() {
doThrow(new SecurityException()).when(mContext)
.enforceCallingOrSelfPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
eq("WifiService"));
// Vebose logging is enabled first in the constructor for WifiServiceImpl, so reset
// before invocation.
reset(mClientModeManager);
mWifiServiceImpl.enableVerboseLogging(WifiManager.VERBOSE_LOGGING_LEVEL_ENABLED);
verify(mWifiSettingsConfigStore, never()).put(
WIFI_VERBOSE_LOGGING_ENABLED, anyBoolean());
verify(mActiveModeWarden, never()).enableVerboseLogging(anyBoolean());
}
/**
* Verify that the CONNECT_NETWORK message received from an app without
* one of the privileged permission is rejected with a security exception.
*/
@Test
public void testConnectNetworkWithoutPrivilegedPermission() throws Exception {
try {
mWifiServiceImpl.connect(mock(WifiConfiguration.class), TEST_NETWORK_ID,
mock(IActionListener.class));
fail();
} catch (SecurityException e) {
mLooper.dispatchAll();
verify(mConnectHelper, never()).connectToNetwork(any(), any(), anyInt());
}
}
/**
* Verify that the FORGET_NETWORK message received from an app without
* one of the privileged permission is rejected with a security exception.
*/
@Test
public void testForgetNetworkWithoutPrivilegedPermission() throws Exception {
try {
mWifiServiceImpl.forget(TEST_NETWORK_ID, mock(IActionListener.class));
fail();
} catch (SecurityException e) {
mLooper.dispatchAll();
verify(mWifiConfigManager, never()).removeNetwork(anyInt(), anyInt(), any());
}
}
/**
* Verify that the SAVE_NETWORK message received from an app without
* one of the privileged permission is rejected with a security exception.
*/
@Test
public void testSaveNetworkWithoutPrivilegedPermission() throws Exception {
try {
mWifiServiceImpl.save(mock(WifiConfiguration.class), mock(IActionListener.class));
fail();
} catch (SecurityException e) {
mLooper.dispatchAll();
verify(mWifiConfigManager, never()).updateBeforeSaveNetwork(any(), anyInt());
}
}
/**
* Verify that the CONNECT_NETWORK message received from an app with
* one of the privileged permission is forwarded to ClientModeManager.
*/
@Test
public void testConnectNetworkWithPrivilegedPermission() throws Exception {
when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED);
when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(true);
when(mWifiConfigManager.addOrUpdateNetwork(any(), anyInt()))
.thenReturn(new NetworkUpdateResult(TEST_NETWORK_ID));
WifiConfiguration config = new WifiConfiguration();
config.SSID = TEST_SSID;
when(mWifiConfigManager.getConfiguredNetwork(TEST_NETWORK_ID)).thenReturn(config);
mWifiServiceImpl.connect(config, TEST_NETWORK_ID, mock(IActionListener.class));
mLooper.dispatchAll();
verify(mWifiConfigManager).addOrUpdateNetwork(eq(config), anyInt());
verify(mConnectHelper).connectToNetwork(any(NetworkUpdateResult.class),
any(ActionListenerWrapper.class), anyInt());
verify(mWifiMetrics).logUserActionEvent(eq(UserActionEvent.EVENT_ADD_OR_UPDATE_NETWORK),
anyInt());
}
@Test
public void connectToNewNetwork_success() throws Exception {
when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED);
when(mWifiPermissionsUtil.isLocationModeEnabled()).thenReturn(true);
NetworkUpdateResult result = new NetworkUpdateResult(TEST_NETWORK_ID);
when(mWifiConfigManager.addOrUpdateNetwork(eq(mWifiConfig), anyInt()))
.thenReturn(result);
when(mWifiConfigManager.getConfiguredNetwork(TEST_NETWORK_ID)).thenReturn(mWifiConfig);
mWifiServiceImpl.connect(mWifiConfig, WifiConfiguration.INVALID_NETWORK_ID,
mActionListener);
mLooper.dispatchAll();
ArgumentCaptor<WifiConfiguration> configCaptor =
ArgumentCaptor.forClass(WifiConfiguration.class);
verify(mWifiConfigManager).addOrUpdateNetwork(configCaptor.capture(), anyInt());
assertThat(configCaptor.getValue().networkId).isEqualTo(TEST_NETWORK_ID);
verify(mConnectHelper).connectToNetwork(eq(result), any(), anyInt());
verify(mContextAsUser).sendBroadcastWithMultiplePermissions(
mIntentCaptor.capture(),
aryEq(new String[]{
android.Manifest.permission.RECEIVE_WIFI_CREDENTIAL_CHANGE,
android.Manifest.permission.ACCESS_FINE_LOCATION,
}));
Intent intent = mIntentCaptor.getValue();
assertThat(intent.getAction()).isEqualTo(WifiManager.WIFI_CREDENTIAL_CHANGED_ACTION);
assertThat(intent.getStringExtra(WifiManager.EXTRA_WIFI_CREDENTIAL_SSID))
.isEqualTo(TEST_SSID);
assertThat(intent.getIntExtra(WifiManager.EXTRA_WIFI_CREDENTIAL_EVENT_TYPE, -1))
.isEqualTo(WifiManager.WIFI_CREDENTIAL_SAVED);
}
@Test
public void connectToNewNetwork_failure() throws Exception {
when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED);
when(mWifiConfigManager.addOrUpdateNetwork(eq(mWifiConfig), anyInt()))
.thenReturn(NetworkUpdateResult.makeFailed());
when(mWifiPermissionsUtil.isLocationModeEnabled()).thenReturn(true);
mWifiServiceImpl.connect(mWifiConfig, WifiConfiguration.INVALID_NETWORK_ID,
mActionListener);
mLooper.dispatchAll();
verify(mWifiConfigManager).addOrUpdateNetwork(eq(mWifiConfig), anyInt());
verify(mClientModeManager, never()).connectNetwork(any(), any(), anyInt());
verify(mContextAsUser, never()).sendBroadcastWithMultiplePermissions(any(), any());
verify(mActionListener).onFailure(WifiManager.ERROR);
verify(mActionListener, never()).onSuccess();
}
@Test
public void connectToExistingNetwork() throws Exception {
when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED);
when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(true);
when(mWifiPermissionsUtil.isLocationModeEnabled()).thenReturn(true);
when(mWifiConfigManager.getConfiguredNetwork(TEST_NETWORK_ID)).thenReturn(mWifiConfig);
mWifiServiceImpl.connect(null, TEST_NETWORK_ID, mActionListener);
mLooper.dispatchAll();
verify(mWifiConfigManager, never()).addOrUpdateNetwork(any(), anyInt());
verify(mConnectHelper).connectToNetwork(
eq(new NetworkUpdateResult(TEST_NETWORK_ID)), any(), anyInt());
verify(mContextAsUser, never()).sendBroadcastWithMultiplePermissions(any(), any());
verify(mWifiMetrics).logUserActionEvent(eq(UserActionEvent.EVENT_MANUAL_CONNECT), anyInt());
}
@Test
public void connectToSimBasedNetworkWhenSimPresent() {
WifiConfiguration config = WifiConfigurationTestUtil.createEapNetwork(
WifiEnterpriseConfig.Eap.SIM, WifiEnterpriseConfig.Phase2.NONE);
when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED);
when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(true);
when(mWifiPermissionsUtil.isLocationModeEnabled()).thenReturn(true);
when(mWifiConfigManager.getConfiguredNetwork(TEST_NETWORK_ID)).thenReturn(config);
when(mWifiCarrierInfoManager.getBestMatchSubscriptionId(any())).thenReturn(TEST_SUB_ID);
when(mWifiCarrierInfoManager.isSimReady(TEST_SUB_ID)).thenReturn(true);
mWifiServiceImpl.connect(null, TEST_NETWORK_ID, mActionListener);
mLooper.dispatchAll();
verify(mWifiConfigManager, never()).addOrUpdateNetwork(any(), anyInt());
verify(mConnectHelper).connectToNetwork(
eq(new NetworkUpdateResult(TEST_NETWORK_ID)), any(), anyInt());
verify(mContextAsUser, never()).sendBroadcastWithMultiplePermissions(any(), any());
verify(mWifiMetrics).logUserActionEvent(eq(UserActionEvent.EVENT_MANUAL_CONNECT), anyInt());
}
@Test
public void connectToSimBasedNetworkWhenSimAbsent() {
WifiConfiguration config = WifiConfigurationTestUtil.createEapNetwork(
WifiEnterpriseConfig.Eap.SIM, WifiEnterpriseConfig.Phase2.NONE);
when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED);
when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(true);
when(mWifiPermissionsUtil.isLocationModeEnabled()).thenReturn(true);
when(mWifiConfigManager.getConfiguredNetwork(TEST_NETWORK_ID)).thenReturn(config);
when(mWifiCarrierInfoManager.getBestMatchSubscriptionId(any())).thenReturn(TEST_SUB_ID);
when(mWifiCarrierInfoManager.isSimReady(TEST_SUB_ID)).thenReturn(false);
mWifiServiceImpl.connect(null, TEST_NETWORK_ID, mActionListener);
mLooper.dispatchAll();
verify(mWifiConfigManager, never()).addOrUpdateNetwork(any(), anyInt());
verify(mConnectHelper, never()).connectToNetwork(any(), any(), anyInt());
verify(mContextAsUser, never()).sendBroadcastWithMultiplePermissions(any(), any());
verify(mWifiMetrics).logUserActionEvent(eq(UserActionEvent.EVENT_MANUAL_CONNECT), anyInt());
}
@Test
public void connectToSimBasedNetworkRequiresImsiEncryptionButNotReady() {
WifiConfiguration config = WifiConfigurationTestUtil.createEapNetwork(
WifiEnterpriseConfig.Eap.SIM, WifiEnterpriseConfig.Phase2.NONE);
when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED);
when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(true);
when(mWifiPermissionsUtil.isLocationModeEnabled()).thenReturn(true);
when(mWifiConfigManager.getConfiguredNetwork(TEST_NETWORK_ID)).thenReturn(config);
when(mWifiCarrierInfoManager.getBestMatchSubscriptionId(any())).thenReturn(TEST_SUB_ID);
when(mWifiCarrierInfoManager.isSimReady(TEST_SUB_ID)).thenReturn(false);
when(mWifiCarrierInfoManager.requiresImsiEncryption(TEST_SUB_ID)).thenReturn(true);
when(mWifiCarrierInfoManager.isImsiEncryptionInfoAvailable(TEST_SUB_ID)).thenReturn(false);
mWifiServiceImpl.connect(null, TEST_NETWORK_ID, mActionListener);
mLooper.dispatchAll();
verify(mWifiConfigManager, never()).addOrUpdateNetwork(any(), anyInt());
verify(mConnectHelper, never()).connectToNetwork(any(), any(), anyInt());
verify(mContextAsUser, never()).sendBroadcastWithMultiplePermissions(any(), any());
verify(mWifiMetrics).logUserActionEvent(eq(UserActionEvent.EVENT_MANUAL_CONNECT), anyInt());
}
/**
* Verify that the SAVE_NETWORK message received from an app with
* one of the privileged permission is forwarded to ClientModeManager.
*/
@Test
public void testSaveNetworkWithPrivilegedPermission() throws Exception {
when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED);
when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(true);
when(mWifiConfigManager.updateBeforeSaveNetwork(any(), anyInt()))
.thenReturn(new NetworkUpdateResult(TEST_NETWORK_ID));
mWifiServiceImpl.save(mock(WifiConfiguration.class), mock(IActionListener.class));
mLooper.dispatchAll();
verify(mWifiConfigManager).updateBeforeSaveNetwork(any(WifiConfiguration.class), anyInt());
verify(mWifiMetrics).logUserActionEvent(eq(UserActionEvent.EVENT_ADD_OR_UPDATE_NETWORK),
anyInt());
}
@Test
public void saveNetwork_success() throws Exception {
when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED);
when(mWifiPermissionsUtil.isLocationModeEnabled()).thenReturn(true);
NetworkUpdateResult result = new NetworkUpdateResult(TEST_NETWORK_ID);
when(mWifiConfigManager.updateBeforeSaveNetwork(eq(mWifiConfig), anyInt()))
.thenReturn(result);
mWifiServiceImpl.save(mWifiConfig, mActionListener);
mLooper.dispatchAll();
verify(mWifiConfigManager).updateBeforeSaveNetwork(eq(mWifiConfig), anyInt());
verify(mClientModeManager).saveNetwork(eq(result), any(), anyInt());
verify(mContextAsUser).sendBroadcastWithMultiplePermissions(
mIntentCaptor.capture(),
aryEq(new String[]{
android.Manifest.permission.RECEIVE_WIFI_CREDENTIAL_CHANGE,
android.Manifest.permission.ACCESS_FINE_LOCATION,
}));
Intent intent = mIntentCaptor.getValue();
assertThat(intent.getAction()).isEqualTo(WifiManager.WIFI_CREDENTIAL_CHANGED_ACTION);
assertThat(intent.getStringExtra(WifiManager.EXTRA_WIFI_CREDENTIAL_SSID))
.isEqualTo(TEST_SSID);
assertThat(intent.getIntExtra(WifiManager.EXTRA_WIFI_CREDENTIAL_EVENT_TYPE, -1))
.isEqualTo(WifiManager.WIFI_CREDENTIAL_SAVED);
}
@Test
public void saveNetwork_failure() throws Exception {
when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED);
when(mWifiConfigManager.updateBeforeSaveNetwork(eq(mWifiConfig), anyInt()))
.thenReturn(NetworkUpdateResult.makeFailed());
when(mWifiPermissionsUtil.isLocationModeEnabled()).thenReturn(true);
mWifiServiceImpl.save(mWifiConfig, mActionListener);
mLooper.dispatchAll();
verify(mWifiConfigManager).updateBeforeSaveNetwork(eq(mWifiConfig), anyInt());
verify(mClientModeManager, never()).saveNetwork(any(), any(), anyInt());
verify(mContext, never()).sendBroadcastWithMultiplePermissions(any(), any());
verify(mActionListener).onFailure(WifiManager.ERROR);
verify(mActionListener, never()).onSuccess();
}
/**
* Verify that the FORGET_NETWORK message received from an app with
* one of the privileged permission is forwarded to ClientModeManager.
*/
@Test
public void testForgetNetworkWithPrivilegedPermission() throws Exception {
when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED);
when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(true);
when(mWifiConfigManager.removeNetwork(anyInt(), anyInt(), any())).thenReturn(true);
mWifiServiceImpl.forget(TEST_NETWORK_ID, mock(IActionListener.class));
InOrder inOrder = inOrder(mWifiConfigManager, mWifiMetrics);
inOrder.verify(mWifiMetrics).logUserActionEvent(
UserActionEvent.EVENT_FORGET_WIFI, TEST_NETWORK_ID);
mLooper.dispatchAll();
inOrder.verify(mWifiConfigManager).removeNetwork(anyInt(), anyInt(), any());
}
@Test
public void forgetNetwork_success() throws Exception {
when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED);
when(mWifiConfigManager.getConfiguredNetwork(TEST_NETWORK_ID)).thenReturn(mWifiConfig);
when(mWifiConfigManager.removeNetwork(eq(TEST_NETWORK_ID), anyInt(), any()))
.thenReturn(true);
when(mWifiPermissionsUtil.isLocationModeEnabled()).thenReturn(true);
mWifiServiceImpl.forget(TEST_NETWORK_ID, mActionListener);
mLooper.dispatchAll();
verify(mWifiConfigManager).removeNetwork(eq(TEST_NETWORK_ID), anyInt(), any());
verify(mActionListener).onSuccess();
verify(mActionListener, never()).onFailure(WifiManager.ERROR);
verify(mContextAsUser).sendBroadcastWithMultiplePermissions(
mIntentCaptor.capture(),
aryEq(new String[]{
android.Manifest.permission.RECEIVE_WIFI_CREDENTIAL_CHANGE,
android.Manifest.permission.ACCESS_FINE_LOCATION,
}));
Intent intent = mIntentCaptor.getValue();
assertThat(intent.getAction()).isEqualTo(WifiManager.WIFI_CREDENTIAL_CHANGED_ACTION);
assertThat(intent.getStringExtra(WifiManager.EXTRA_WIFI_CREDENTIAL_SSID))
.isEqualTo(TEST_SSID);
assertThat(intent.getIntExtra(WifiManager.EXTRA_WIFI_CREDENTIAL_EVENT_TYPE, -1))
.isEqualTo(WifiManager.WIFI_CREDENTIAL_FORGOT);
}
@Test
public void forgetNetwork_successNoLocation_dontBroadcastSsid() throws Exception {
when(mWifiPermissionsUtil.isLocationModeEnabled()).thenReturn(false);
when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED);
when(mWifiConfigManager.getConfiguredNetwork(TEST_NETWORK_ID)).thenReturn(mWifiConfig);
when(mWifiConfigManager.removeNetwork(eq(TEST_NETWORK_ID), anyInt(), any()))
.thenReturn(true);
mWifiServiceImpl.forget(TEST_NETWORK_ID, mActionListener);
mLooper.dispatchAll();
verify(mWifiConfigManager).removeNetwork(eq(TEST_NETWORK_ID), anyInt(), any());
verify(mActionListener).onSuccess();
verify(mActionListener, never()).onFailure(WifiManager.ERROR);
verify(mContextAsUser).sendBroadcastWithMultiplePermissions(
mIntentCaptor.capture(),
aryEq(new String[]{
android.Manifest.permission.RECEIVE_WIFI_CREDENTIAL_CHANGE,
android.Manifest.permission.ACCESS_FINE_LOCATION,
}));
Intent intent = mIntentCaptor.getValue();
assertThat(intent.getAction()).isEqualTo(WifiManager.WIFI_CREDENTIAL_CHANGED_ACTION);
// SSID is null if location is disabled
assertThat(intent.getStringExtra(WifiManager.EXTRA_WIFI_CREDENTIAL_SSID)).isNull();
assertThat(intent.getIntExtra(WifiManager.EXTRA_WIFI_CREDENTIAL_EVENT_TYPE, -1))
.isEqualTo(WifiManager.WIFI_CREDENTIAL_FORGOT);
}
@Test
public void forgetNetwork_failed() throws Exception {
when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED);
when(mWifiConfigManager.removeNetwork(eq(TEST_NETWORK_ID), anyInt(), any()))
.thenReturn(false);
when(mWifiPermissionsUtil.isLocationModeEnabled()).thenReturn(true);
mWifiServiceImpl.forget(TEST_NETWORK_ID, mActionListener);
mLooper.dispatchAll();
verify(mActionListener, never()).onSuccess();
verify(mActionListener).onFailure(WifiManager.ERROR);
verify(mWifiConfigManager).removeNetwork(eq(TEST_NETWORK_ID), anyInt(), any());
verify(mContextAsUser, never()).sendBroadcastWithMultiplePermissions(any(), any());
}
/**
* Tests the scenario when a scan request arrives while the device is idle. In this case
* the scan is done when idle mode ends.
*/
@Test
public void testHandleDelayedScanAfterIdleMode() throws Exception {
when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false);
when(mWifiInjector.getPasspointProvisionerHandlerThread())
.thenReturn(mock(HandlerThread.class));
mLooper.startAutoDispatch();
mWifiServiceImpl.checkAndStartWifi();
mWifiServiceImpl.handleBootCompleted();
mLooper.stopAutoDispatch();
verify(mContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
(IntentFilter) argThat(new IdleModeIntentMatcher()));
// Tell the wifi service that the device became idle.
when(mPowerManager.isDeviceIdleMode()).thenReturn(true);
TestUtil.sendIdleModeChanged(mBroadcastReceiverCaptor.getValue(), mContext);
// Send a scan request while the device is idle.
mWifiThreadRunner.prepareForAutoDispatch();
mLooper.startAutoDispatch();
assertFalse(mWifiServiceImpl.startScan(SCAN_PACKAGE_NAME, TEST_FEATURE_ID));
mLooper.stopAutoDispatch();
// No scans must be made yet as the device is idle.
verify(mScanRequestProxy, never()).startScan(Process.myUid(), SCAN_PACKAGE_NAME);
// Tell the wifi service that idle mode ended.
when(mPowerManager.isDeviceIdleMode()).thenReturn(false);
mWifiThreadRunner.prepareForAutoDispatch();
mLooper.startAutoDispatch();
TestUtil.sendIdleModeChanged(mBroadcastReceiverCaptor.getValue(), mContext);
mLooper.stopAutoDispatch();
// Must scan now.
verify(mScanRequestProxy).startScan(Process.myUid(), TEST_PACKAGE_NAME);
// The app ops check is executed with this package's identity (not the identity of the
// original remote caller who requested the scan while idle).
verify(mAppOpsManager).noteOp(
AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Process.myUid(), TEST_PACKAGE_NAME);
// Send another scan request. The device is not idle anymore, so it must be executed
// immediately.
mWifiThreadRunner.prepareForAutoDispatch();
mLooper.startAutoDispatch();
assertTrue(mWifiServiceImpl.startScan(SCAN_PACKAGE_NAME, TEST_FEATURE_ID));
mLooper.stopAutoDispatch();
verify(mScanRequestProxy).startScan(Process.myUid(), SCAN_PACKAGE_NAME);
}
/**
* Verify that if the caller has NETWORK_SETTINGS permission, then it doesn't need
* CHANGE_WIFI_STATE permission.
*/
@Test
public void testDisconnectWithNetworkSettingsPerm() throws Exception {
when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED);
doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission(
android.Manifest.permission.CHANGE_WIFI_STATE, "WifiService");
doThrow(new SecurityException()).when(mAppOpsManager)
.noteOp(AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Process.myUid(), TEST_PACKAGE_NAME);
assertTrue(mWifiServiceImpl.disconnect(TEST_PACKAGE_NAME));
mLooper.dispatchAll();
verify(mClientModeManager).disconnect();
}
/**
* Verify that if the caller doesn't have NETWORK_SETTINGS permission, it could still
* get access with the CHANGE_WIFI_STATE permission.
*/
@Test
public void testDisconnectWithChangeWifiStatePerm() throws Exception {
assertFalse(mWifiServiceImpl.disconnect(TEST_PACKAGE_NAME));
mLooper.dispatchAll();
verifyCheckChangePermission(TEST_PACKAGE_NAME);
verify(mClientModeManager, never()).disconnect();
}
/**
* Verify that the operation fails if the caller has neither NETWORK_SETTINGS or
* CHANGE_WIFI_STATE permissions.
*/
@Test
public void testDisconnectRejected() throws Exception {
doThrow(new SecurityException()).when(mAppOpsManager)
.noteOp(AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Process.myUid(), TEST_PACKAGE_NAME);
try {
mWifiServiceImpl.disconnect(TEST_PACKAGE_NAME);
fail();
} catch (SecurityException e) {
}
verifyCheckChangePermission(TEST_PACKAGE_NAME);
verify(mClientModeManager, never()).disconnect();
}
@Test
public void testPackageFullyRemovedBroadcastHandling() throws Exception {
mWifiServiceImpl.checkAndStartWifi();
mLooper.dispatchAll();
verify(mContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
argThat((IntentFilter filter) ->
filter.hasAction(Intent.ACTION_PACKAGE_FULLY_REMOVED)
&& filter.hasAction(Intent.ACTION_PACKAGE_REMOVED)
&& filter.hasAction(Intent.ACTION_PACKAGE_CHANGED)));
int uid = TEST_UID;
String packageName = TEST_PACKAGE_NAME;
doThrow(new PackageManager.NameNotFoundException()).when(mPackageManager)
.getApplicationInfo(TEST_PACKAGE_NAME, 0);
// Send the broadcast
Intent intent = new Intent(Intent.ACTION_PACKAGE_FULLY_REMOVED);
intent.putExtra(Intent.EXTRA_UID, uid);
intent.setData(Uri.fromParts("package", packageName, ""));
mBroadcastReceiverCaptor.getValue().onReceive(mContext, intent);
mLooper.dispatchAll();
ArgumentCaptor<ApplicationInfo> aiCaptor = ArgumentCaptor.forClass(ApplicationInfo.class);
verify(mWifiConfigManager).removeNetworksForApp(aiCaptor.capture());
assertNotNull(aiCaptor.getValue());
assertEquals(uid, aiCaptor.getValue().uid);
assertEquals(packageName, aiCaptor.getValue().packageName);
verify(mScanRequestProxy).clearScanRequestTimestampsForApp(packageName, uid);
verify(mWifiNetworkSuggestionsManager).removeApp(packageName);
verify(mWifiNetworkFactory).removeUserApprovedAccessPointsForApp(packageName);
verify(mPasspointManager).removePasspointProviderWithPackage(packageName);
}
@Test
public void testPackageRemovedBroadcastHandling() throws Exception {
mWifiServiceImpl.checkAndStartWifi();
mLooper.dispatchAll();
verify(mContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
argThat((IntentFilter filter) ->
filter.hasAction(Intent.ACTION_PACKAGE_FULLY_REMOVED)
&& filter.hasAction(Intent.ACTION_PACKAGE_REMOVED)
&& filter.hasAction(Intent.ACTION_PACKAGE_CHANGED)));
int uid = TEST_UID;
String packageName = TEST_PACKAGE_NAME;
// Send the broadcast
Intent intent = new Intent(Intent.ACTION_PACKAGE_REMOVED);
intent.putExtra(Intent.EXTRA_UID, uid);
intent.setData(Uri.fromParts("package", packageName, ""));
mBroadcastReceiverCaptor.getValue().onReceive(mContext, intent);
mLooper.dispatchAll();
ArgumentCaptor<ApplicationInfo> aiCaptor = ArgumentCaptor.forClass(ApplicationInfo.class);
verify(mWifiConfigManager).removeNetworksForApp(aiCaptor.capture());
assertNotNull(aiCaptor.getValue());
assertEquals(uid, aiCaptor.getValue().uid);
assertEquals(packageName, aiCaptor.getValue().packageName);
verify(mScanRequestProxy).clearScanRequestTimestampsForApp(packageName, uid);
verify(mWifiNetworkSuggestionsManager).removeApp(packageName);
verify(mWifiNetworkFactory).removeUserApprovedAccessPointsForApp(packageName);
verify(mPasspointManager).removePasspointProviderWithPackage(packageName);
}
@Test
public void testPackageDisableBroadcastHandling() throws Exception {
mWifiServiceImpl.checkAndStartWifi();
mLooper.dispatchAll();
verify(mContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
argThat((IntentFilter filter) ->
filter.hasAction(Intent.ACTION_PACKAGE_FULLY_REMOVED)
&& filter.hasAction(Intent.ACTION_PACKAGE_REMOVED)
&& filter.hasAction(Intent.ACTION_PACKAGE_CHANGED)));
int uid = TEST_UID;
String packageName = TEST_PACKAGE_NAME;
mPackageInfo.applicationInfo = mApplicationInfo;
mApplicationInfo.enabled = false;
// Send the broadcast
Intent intent = new Intent(Intent.ACTION_PACKAGE_CHANGED);
intent.putExtra(Intent.EXTRA_UID, uid);
intent.setData(Uri.fromParts("package", packageName, ""));
mBroadcastReceiverCaptor.getValue().onReceive(mContext, intent);
mLooper.dispatchAll();
ArgumentCaptor<ApplicationInfo> aiCaptor = ArgumentCaptor.forClass(ApplicationInfo.class);
verify(mWifiConfigManager).removeNetworksForApp(aiCaptor.capture());
assertNotNull(aiCaptor.getValue());
assertEquals(uid, aiCaptor.getValue().uid);
assertEquals(packageName, aiCaptor.getValue().packageName);
verify(mScanRequestProxy).clearScanRequestTimestampsForApp(packageName, uid);
verify(mWifiNetworkSuggestionsManager).removeApp(packageName);
verify(mWifiNetworkFactory).removeUserApprovedAccessPointsForApp(packageName);
verify(mPasspointManager).removePasspointProviderWithPackage(packageName);
}
@Test
public void testPackageRemovedBroadcastHandlingWithNoUid() {
mWifiServiceImpl.checkAndStartWifi();
mLooper.dispatchAll();
verify(mContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
argThat((IntentFilter filter) ->
filter.hasAction(Intent.ACTION_PACKAGE_FULLY_REMOVED)));
String packageName = TEST_PACKAGE_NAME;
// Send the broadcast
Intent intent = new Intent(Intent.ACTION_PACKAGE_REMOVED);
intent.setData(Uri.fromParts("package", packageName, ""));
mBroadcastReceiverCaptor.getValue().onReceive(mContext, intent);
verify(mWifiConfigManager, never()).removeNetworksForApp(any());
mLooper.dispatchAll();
verify(mScanRequestProxy, never()).clearScanRequestTimestampsForApp(anyString(), anyInt());
verify(mWifiNetworkSuggestionsManager, never()).removeApp(anyString());
verify(mWifiNetworkFactory, never()).removeUserApprovedAccessPointsForApp(anyString());
verify(mPasspointManager, never()).removePasspointProviderWithPackage(anyString());
}
@Test
public void testPackageRemovedBroadcastHandlingWithNoPackageName() {
mWifiServiceImpl.checkAndStartWifi();
mLooper.dispatchAll();
verify(mContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
argThat((IntentFilter filter) ->
filter.hasAction(Intent.ACTION_PACKAGE_FULLY_REMOVED)));
int uid = TEST_UID;
// Send the broadcast
Intent intent = new Intent(Intent.ACTION_PACKAGE_FULLY_REMOVED);
intent.putExtra(Intent.EXTRA_UID, uid);
mBroadcastReceiverCaptor.getValue().onReceive(mContext, intent);
verify(mWifiConfigManager, never()).removeNetworksForApp(any());
mLooper.dispatchAll();
verify(mScanRequestProxy, never()).clearScanRequestTimestampsForApp(anyString(), anyInt());
verify(mWifiNetworkSuggestionsManager, never()).removeApp(anyString());
verify(mWifiNetworkFactory, never()).removeUserApprovedAccessPointsForApp(anyString());
verify(mPasspointManager, never()).removePasspointProviderWithPackage(anyString());
}
@Test
public void testUserRemovedBroadcastHandling() {
when(mWifiInjector.getPasspointProvisionerHandlerThread())
.thenReturn(mock(HandlerThread.class));
mLooper.startAutoDispatch();
mWifiServiceImpl.checkAndStartWifi();
mWifiServiceImpl.handleBootCompleted();
mLooper.stopAutoDispatch();
verify(mContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
argThat((IntentFilter filter) ->
filter.hasAction(Intent.ACTION_USER_REMOVED)));
UserHandle userHandle = UserHandle.of(TEST_USER_HANDLE);
// Send the broadcast
Intent intent = new Intent(Intent.ACTION_USER_REMOVED);
intent.putExtra(Intent.EXTRA_USER, userHandle);
mBroadcastReceiverCaptor.getValue().onReceive(mContext, intent);
mLooper.dispatchAll();
verify(mWifiConfigManager).removeNetworksForUser(userHandle.getIdentifier());
}
@Test
public void testBluetoothBroadcastHandling() {
when(mWifiInjector.getPasspointProvisionerHandlerThread())
.thenReturn(mock(HandlerThread.class));
mLooper.startAutoDispatch();
mWifiServiceImpl.checkAndStartWifi();
mWifiServiceImpl.handleBootCompleted();
mLooper.stopAutoDispatch();
verify(mContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
argThat((IntentFilter filter) ->
filter.hasAction(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED)
&& filter.hasAction(BluetoothAdapter.ACTION_STATE_CHANGED)));
{
Intent intent = new Intent(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED);
intent.putExtra(BluetoothAdapter.EXTRA_CONNECTION_STATE,
BluetoothAdapter.STATE_DISCONNECTED);
mBroadcastReceiverCaptor.getValue().onReceive(mContext, intent);
mLooper.dispatchAll();
verify(mWifiGlobals).setBluetoothConnected(false);
for (ClientModeManager cmm : mClientModeManagers) {
verify(cmm).onBluetoothConnectionStateChanged();
}
}
{
Intent intent = new Intent(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED);
intent.putExtra(BluetoothAdapter.EXTRA_CONNECTION_STATE,
BluetoothAdapter.STATE_CONNECTED);
mBroadcastReceiverCaptor.getValue().onReceive(mContext, intent);
mLooper.dispatchAll();
verify(mWifiGlobals).setBluetoothConnected(true);
for (ClientModeManager cmm : mClientModeManagers) {
verify(cmm, times(2)).onBluetoothConnectionStateChanged();
}
}
{
Intent intent = new Intent(BluetoothAdapter.ACTION_STATE_CHANGED);
intent.putExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.STATE_OFF);
mBroadcastReceiverCaptor.getValue().onReceive(mContext, intent);
mLooper.dispatchAll();
verify(mWifiGlobals).setBluetoothEnabled(false);
for (ClientModeManager cmm : mClientModeManagers) {
verify(cmm, times(3)).onBluetoothConnectionStateChanged();
}
}
{
Intent intent = new Intent(BluetoothAdapter.ACTION_STATE_CHANGED);
intent.putExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.STATE_ON);
mBroadcastReceiverCaptor.getValue().onReceive(mContext, intent);
mLooper.dispatchAll();
verify(mWifiGlobals).setBluetoothEnabled(true);
for (ClientModeManager cmm : mClientModeManagers) {
verify(cmm, times(4)).onBluetoothConnectionStateChanged();
}
}
}
@Test
public void testUserRemovedBroadcastHandlingWithWrongIntentAction() {
when(mWifiInjector.getPasspointProvisionerHandlerThread())
.thenReturn(mock(HandlerThread.class));
mLooper.startAutoDispatch();
mWifiServiceImpl.checkAndStartWifi();
mWifiServiceImpl.handleBootCompleted();
mLooper.stopAutoDispatch();
verify(mContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
argThat((IntentFilter filter) ->
filter.hasAction(Intent.ACTION_USER_REMOVED)));
UserHandle userHandle = UserHandle.of(TEST_USER_HANDLE);
// Send the broadcast with wrong action
Intent intent = new Intent(Intent.ACTION_USER_FOREGROUND);
intent.putExtra(Intent.EXTRA_USER, userHandle);
mBroadcastReceiverCaptor.getValue().onReceive(mContext, intent);
verify(mWifiConfigManager, never()).removeNetworksForUser(anyInt());
}
private class IdleModeIntentMatcher implements ArgumentMatcher<IntentFilter> {
@Override
public boolean matches(IntentFilter filter) {
return filter.hasAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED);
}
}
/**
* Verifies that enforceChangePermission(String package) is called and the caller doesn't
* have NETWORK_SETTINGS permission
*/
private void verifyCheckChangePermission(String callingPackageName) {
verify(mContext, atLeastOnce())
.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
anyInt(), anyInt());
verify(mContext, atLeastOnce()).enforceCallingOrSelfPermission(
android.Manifest.permission.CHANGE_WIFI_STATE, "WifiService");
verify(mAppOpsManager, atLeastOnce()).noteOp(
AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Process.myUid(), callingPackageName);
}
private WifiConfiguration createValidWifiApConfiguration() {
WifiConfiguration apConfig = new WifiConfiguration();
apConfig.SSID = "TestAp";
apConfig.preSharedKey = "thisIsABadPassword";
apConfig.allowedKeyManagement.set(KeyMgmt.WPA2_PSK);
apConfig.apBand = WifiConfiguration.AP_BAND_2GHZ;
return apConfig;
}
private SoftApConfiguration createValidSoftApConfiguration() {
return new SoftApConfiguration.Builder()
.setSsid("TestAp")
.setPassphrase("thisIsABadPassword", SoftApConfiguration.SECURITY_TYPE_WPA2_PSK)
.setBand(SoftApConfiguration.BAND_2GHZ)
.build();
}
/**
* Verifies that sim state change does not set or reset the country code
*/
@Test
public void testSimStateChangeDoesNotResetCountryCode() {
mWifiServiceImpl.checkAndStartWifi();
mLooper.dispatchAll();
verify(mContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
(IntentFilter) argThat((IntentFilter filter) ->
filter.hasAction(TelephonyManager.ACTION_SIM_CARD_STATE_CHANGED)));
int userHandle = TEST_USER_HANDLE;
// Send the broadcast
Intent intent = new Intent(TelephonyManager.ACTION_SIM_CARD_STATE_CHANGED);
intent.putExtra(Intent.EXTRA_USER_HANDLE, userHandle);
mBroadcastReceiverCaptor.getValue().onReceive(mContext, intent);
verify(mWifiCountryCode, never()).setTelephonyCountryCodeAndUpdate(any());
}
/**
* Verifies that sim state change does not set or reset the country code
*/
@Test
public void testSimStateChangeDoesNotResetCountryCodeForRebroadcastedIntent() {
mWifiServiceImpl.checkAndStartWifi();
mLooper.dispatchAll();
verify(mContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
(IntentFilter) argThat((IntentFilter filter) ->
filter.hasAction(TelephonyManager.ACTION_SIM_CARD_STATE_CHANGED)));
int userHandle = TEST_USER_HANDLE;
// Send the broadcast
Intent intent = new Intent(TelephonyManager.ACTION_SIM_CARD_STATE_CHANGED);
intent.putExtra(Intent.EXTRA_USER_HANDLE, userHandle);
intent.putExtra(TelephonyManager.EXTRA_SIM_STATE, Intent.SIM_STATE_ABSENT);
mBroadcastReceiverCaptor.getValue().onReceive(mContext, intent);
verify(mWifiCountryCode, never()).setTelephonyCountryCodeAndUpdate(any());
}
/**
* Verify removing sim will also remove an ephemeral Passpoint Provider. And reset carrier
* privileged suggestor apps.
*/
@Test
public void testResetSimNetworkWhenRemovingSim() throws Exception {
mWifiServiceImpl.checkAndStartWifi();
mLooper.dispatchAll();
verify(mContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
argThat((IntentFilter filter) ->
filter.hasAction(TelephonyManager.ACTION_SIM_CARD_STATE_CHANGED)));
Intent intent = new Intent(TelephonyManager.ACTION_SIM_CARD_STATE_CHANGED);
intent.putExtra(TelephonyManager.EXTRA_SIM_STATE, TelephonyManager.SIM_STATE_ABSENT);
mBroadcastReceiverCaptor.getValue().onReceive(mContext, intent);
mLooper.dispatchAll();
verify(mWifiConfigManager).resetSimNetworks();
verify(mWifiConfigManager).stopRestrictingAutoJoinToSubscriptionId();
verify(mSimRequiredNotifier, never()).dismissSimRequiredNotification();
verify(mWifiNetworkSuggestionsManager).resetCarrierPrivilegedApps();
verify(mWifiConfigManager, never()).removeAllEphemeralOrPasspointConfiguredNetworks();
verify(mWifiNetworkSuggestionsManager).resetSimNetworkSuggestions();
verify(mPasspointManager).resetSimPasspointNetwork();
}
/**
* Verify inserting sim will reset carrier privileged suggestor apps.
* and remove any previous notifications due to sim removal
*/
@Test
public void testResetCarrierPrivilegedAppsWhenInsertingSim() throws Exception {
mWifiServiceImpl.checkAndStartWifi();
mLooper.dispatchAll();
verify(mContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
argThat((IntentFilter filter) ->
filter.hasAction(TelephonyManager.ACTION_SIM_APPLICATION_STATE_CHANGED)));
Intent intent = new Intent(TelephonyManager.ACTION_SIM_APPLICATION_STATE_CHANGED);
intent.putExtra(TelephonyManager.EXTRA_SIM_STATE, TelephonyManager.SIM_STATE_LOADED);
mBroadcastReceiverCaptor.getValue().onReceive(mContext, intent);
mLooper.dispatchAll();
verify(mWifiConfigManager, never()).resetSimNetworks();
verify(mPasspointManager, never()).resetSimPasspointNetwork();
verify(mWifiNetworkSuggestionsManager, never()).resetSimNetworkSuggestions();
verify(mWifiConfigManager, never()).stopRestrictingAutoJoinToSubscriptionId();
verify(mSimRequiredNotifier).dismissSimRequiredNotification();
verify(mWifiNetworkSuggestionsManager).resetCarrierPrivilegedApps();
verify(mWifiConfigManager, never()).removeAllEphemeralOrPasspointConfiguredNetworks();
verify(mWifiConfigManager).enableTemporaryDisabledNetworks();
verify(mWifiConnectivityManager).forceConnectivityScan(any());
}
@Test
public void testResetSimNetworkWhenDefaultDataSimChanged() throws Exception {
mWifiServiceImpl.checkAndStartWifi();
mLooper.dispatchAll();
verify(mContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
argThat((IntentFilter filter) ->
filter.hasAction(
TelephonyManager.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED)));
Intent intent = new Intent(TelephonyManager.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED);
intent.putExtra("subscription", 1);
mBroadcastReceiverCaptor.getValue().onReceive(mContext, intent);
mLooper.dispatchAll();
verify(mWifiConfigManager).resetSimNetworks();
verify(mWifiConfigManager).stopRestrictingAutoJoinToSubscriptionId();
verify(mSimRequiredNotifier).dismissSimRequiredNotification();
verify(mWifiNetworkSuggestionsManager).resetCarrierPrivilegedApps();
verify(mWifiConfigManager).removeEphemeralCarrierNetworks();
verify(mWifiNetworkSuggestionsManager).resetSimNetworkSuggestions();
verify(mPasspointManager).resetSimPasspointNetwork();
verify(mWifiDataStall).resetPhoneStateListener();
}
/**
* Verify that a call to registerTrafficStateCallback throws a SecurityException if the caller
* does not have NETWORK_SETTINGS permission.
*/
@Test
public void registerTrafficStateCallbackThrowsSecurityExceptionOnMissingPermissions() {
doThrow(new SecurityException()).when(mContext)
.enforceCallingOrSelfPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
eq("WifiService"));
try {
mWifiServiceImpl.registerTrafficStateCallback(mTrafficStateCallback);
fail("expected SecurityException");
} catch (SecurityException expected) {
}
}
/**
* Verify that a call to registerTrafficStateCallback throws an IllegalArgumentException if the
* parameters are not provided.
*/
@Test
public void registerTrafficStateCallbackThrowsIllegalArgumentExceptionOnInvalidArguments() {
try {
mWifiServiceImpl.registerTrafficStateCallback(null);
fail("expected IllegalArgumentException");
} catch (IllegalArgumentException expected) {
}
}
/**
* Verify that a call to unregisterTrafficStateCallback throws a SecurityException if the caller
* does not have NETWORK_SETTINGS permission.
*/
@Test
public void unregisterTrafficStateCallbackThrowsSecurityExceptionOnMissingPermissions() {
doThrow(new SecurityException()).when(mContext)
.enforceCallingOrSelfPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
eq("WifiService"));
try {
mWifiServiceImpl.unregisterTrafficStateCallback(mTrafficStateCallback);
fail("expected SecurityException");
} catch (SecurityException expected) {
}
}
/**
* Verify that registerTrafficStateCallback adds callback to {@link WifiTrafficPoller}.
*/
@Test
public void registerTrafficStateCallbackAndVerify() throws Exception {
mWifiServiceImpl.registerTrafficStateCallback(mTrafficStateCallback);
mLooper.dispatchAll();
verify(mWifiTrafficPoller).addCallback(mTrafficStateCallback);
}
/**
* Verify that unregisterTrafficStateCallback removes callback from {@link WifiTrafficPoller}.
*/
@Test
public void unregisterTrafficStateCallbackAndVerify() throws Exception {
mWifiServiceImpl.unregisterTrafficStateCallback(mTrafficStateCallback);
mLooper.dispatchAll();
verify(mWifiTrafficPoller).removeCallback(mTrafficStateCallback);
}
/**
* Verify that a call to registerNetworkRequestMatchCallback throws a SecurityException if the
* caller does not have NETWORK_SETTINGS permission.
*/
@Test
public void registerNetworkRequestMatchCallbackThrowsSecurityExceptionOnMissingPermissions() {
doThrow(new SecurityException()).when(mContext)
.enforceCallingOrSelfPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
eq("WifiService"));
try {
mWifiServiceImpl.registerNetworkRequestMatchCallback(mNetworkRequestMatchCallback);
fail("expected SecurityException");
} catch (SecurityException expected) {
}
}
/**
* Verify that a call to registerNetworkRequestMatchCallback throws an IllegalArgumentException
* if the parameters are not provided.
*/
@Test
public void
registerNetworkRequestMatchCallbackThrowsIllegalArgumentExceptionOnInvalidArguments() {
try {
mWifiServiceImpl.registerNetworkRequestMatchCallback(null);
fail("expected IllegalArgumentException");
} catch (IllegalArgumentException expected) {
}
}
/**
* Verify that a call to unregisterNetworkRequestMatchCallback throws a SecurityException if the
* caller does not have NETWORK_SETTINGS permission.
*/
@Test
public void unregisterNetworkRequestMatchCallbackThrowsSecurityExceptionOnMissingPermissions() {
doThrow(new SecurityException()).when(mContext)
.enforceCallingOrSelfPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
eq("WifiService"));
try {
mWifiServiceImpl.unregisterNetworkRequestMatchCallback(mNetworkRequestMatchCallback);
fail("expected SecurityException");
} catch (SecurityException expected) {
}
}
/**
* Verify that registerNetworkRequestMatchCallback adds callback to
* {@link ClientModeManager}.
*/
@Test
public void registerNetworkRequestMatchCallbackAndVerify() throws Exception {
mWifiServiceImpl.registerNetworkRequestMatchCallback(mNetworkRequestMatchCallback);
mLooper.dispatchAll();
verify(mWifiNetworkFactory).addCallback(mNetworkRequestMatchCallback);
}
/**
* Verify that unregisterNetworkRequestMatchCallback removes callback from
* {@link ClientModeManager}.
*/
@Test
public void unregisterNetworkRequestMatchCallbackAndVerify() throws Exception {
mWifiServiceImpl.unregisterNetworkRequestMatchCallback(mNetworkRequestMatchCallback);
mLooper.dispatchAll();
verify(mWifiNetworkFactory).removeCallback(mNetworkRequestMatchCallback);
}
/**
* Verify that Wifi configuration and Passpoint configuration are removed in factoryReset.
*/
@Test
public void testFactoryReset() throws Exception {
when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED);
when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(true);
final String fqdn = "example.com";
WifiConfiguration network = WifiConfigurationTestUtil.createOpenNetwork();
PasspointConfiguration config = new PasspointConfiguration();
HomeSp homeSp = new HomeSp();
homeSp.setFqdn(fqdn);
config.setHomeSp(homeSp);
Credential credential = new Credential();
credential.setRealm("example.com");
config.setCredential(credential);
when(mWifiConfigManager.getSavedNetworks(anyInt()))
.thenReturn(Arrays.asList(network));
when(mPasspointManager.getProviderConfigs(anyInt(), anyBoolean()))
.thenReturn(Arrays.asList(config));
mLooper.startAutoDispatch();
mWifiServiceImpl.factoryReset(TEST_PACKAGE_NAME);
mLooper.stopAutoDispatchAndIgnoreExceptions();
// Let the final post inside the |factoryReset| method run to completion.
mLooper.dispatchAll();
verify(mWifiConfigManager).removeNetwork(
network.networkId, Binder.getCallingUid(), TEST_PACKAGE_NAME);
verify(mPasspointManager).removeProvider(anyInt(), anyBoolean(), eq(config.getUniqueId()),
isNull());
verify(mPasspointManager).clearAnqpRequestsAndFlushCache();
verify(mWifiConfigManager).clearUserTemporarilyDisabledList();
verify(mWifiConfigManager).removeAllEphemeralOrPasspointConfiguredNetworks();
verify(mWifiNetworkFactory).clear();
verify(mWifiNetworkSuggestionsManager).clear();
verify(mWifiScoreCard).clear();
verify(mWifiHealthMonitor).clear();
verify(mPasspointManager).getProviderConfigs(anyInt(), anyBoolean());
}
/**
* Verify that a call to factoryReset throws a SecurityException if the caller does not have
* the NETWORK_SETTINGS permission.
*/
@Test
public void testFactoryResetWithoutNetworkSettingsPermission() throws Exception {
doThrow(new SecurityException()).when(mContext)
.enforceCallingOrSelfPermission(eq(Manifest.permission.NETWORK_SETTINGS),
eq("WifiService"));
try {
mWifiServiceImpl.factoryReset(TEST_PACKAGE_NAME);
fail();
} catch (SecurityException e) {
}
verify(mWifiConfigManager, never()).getSavedNetworks(anyInt());
verify(mPasspointManager, never()).getProviderConfigs(anyInt(), anyBoolean());
}
/**
* Verify that add or update networks is not allowed for apps targeting Q SDK.
*/
@Test
public void testAddOrUpdateNetworkIsNotAllowedForAppsTargetingQSdk() throws Exception {
doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManager)
.noteOp(AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Process.myUid(), TEST_PACKAGE_NAME);
when(mWifiConfigManager.addOrUpdateNetwork(any(), anyInt(), any())).thenReturn(
new NetworkUpdateResult(0));
WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork();
mLooper.startAutoDispatch();
assertEquals(-1, mWifiServiceImpl.addOrUpdateNetwork(config, TEST_PACKAGE_NAME));
mLooper.stopAutoDispatchAndIgnoreExceptions();
verifyCheckChangePermission(TEST_PACKAGE_NAME);
verify(mWifiConfigManager, never()).addOrUpdateNetwork(any(), anyInt(), any());
verify(mWifiMetrics, never()).incrementNumAddOrUpdateNetworkCalls();
}
/**
* Verify that add or update networks is allowed for apps targeting below Q SDK.
*/
@Test
public void testAddOrUpdateNetworkIsAllowedForAppsTargetingBelowQSdk() throws Exception {
doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManager)
.noteOp(AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Process.myUid(), TEST_PACKAGE_NAME);
when(mWifiConfigManager.addOrUpdateNetwork(any(), anyInt(), any())).thenReturn(
new NetworkUpdateResult(0));
when(mWifiPermissionsUtil.isTargetSdkLessThan(anyString(),
eq(Build.VERSION_CODES.Q), anyInt())).thenReturn(true);
WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork();
mLooper.startAutoDispatch();
assertEquals(0, WifiConfigurationUtil.removeSecurityTypeFromNetworkId(
mWifiServiceImpl.addOrUpdateNetwork(config, TEST_PACKAGE_NAME)));
mLooper.stopAutoDispatchAndIgnoreExceptions();
verifyCheckChangePermission(TEST_PACKAGE_NAME);
verify(mWifiConfigManager).addOrUpdateNetwork(any(), anyInt(), any());
verify(mWifiMetrics).incrementNumAddOrUpdateNetworkCalls();
}
/**
* Verify that add or update networks is allowed for settings app.
*/
@Test
public void testAddOrUpdateNetworkIsAllowedForSettingsApp() throws Exception {
when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED);
mApplicationInfo.targetSdkVersion = Build.VERSION_CODES.P;
when(mWifiConfigManager.addOrUpdateNetwork(any(), anyInt(), any())).thenReturn(
new NetworkUpdateResult(0));
WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork();
mLooper.startAutoDispatch();
assertEquals(0, WifiConfigurationUtil.removeSecurityTypeFromNetworkId(
mWifiServiceImpl.addOrUpdateNetwork(config, TEST_PACKAGE_NAME)));
mLooper.stopAutoDispatchAndIgnoreExceptions();
// Ensure that we don't check for change permission.
verify(mContext, never()).enforceCallingOrSelfPermission(
android.Manifest.permission.CHANGE_WIFI_STATE, "WifiService");
verify(mAppOpsManager, never()).noteOp(
AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Process.myUid(), TEST_PACKAGE_NAME);
verify(mWifiConfigManager).addOrUpdateNetwork(any(), anyInt(), any());
verify(mWifiMetrics).incrementNumAddOrUpdateNetworkCalls();
}
/**
* Verify that add or update networks is allowed for system apps.
*/
@Test
public void testAddOrUpdateNetworkIsAllowedForSystemApp() throws Exception {
doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManager)
.noteOp(AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Process.myUid(), TEST_PACKAGE_NAME);
when(mWifiPermissionsUtil.isSystem(anyString(), anyInt())).thenReturn(true);
when(mWifiConfigManager.addOrUpdateNetwork(any(), anyInt(), any())).thenReturn(
new NetworkUpdateResult(0));
WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork();
mLooper.startAutoDispatch();
assertEquals(0, WifiConfigurationUtil.removeSecurityTypeFromNetworkId(
mWifiServiceImpl.addOrUpdateNetwork(config, TEST_PACKAGE_NAME)));
mLooper.stopAutoDispatchAndIgnoreExceptions();
verifyCheckChangePermission(TEST_PACKAGE_NAME);
verify(mWifiConfigManager).addOrUpdateNetwork(any(), anyInt(), any());
verify(mWifiMetrics).incrementNumAddOrUpdateNetworkCalls();
}
/**
* Verify that add or update networks is allowed for apps holding system alert permission.
*/
@Test
public void testAddOrUpdateNetworkIsAllowedForAppsWithSystemAlertPermission() throws Exception {
doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManager)
.noteOp(AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Process.myUid(), TEST_PACKAGE_NAME);
when(mWifiConfigManager.addOrUpdateNetwork(any(), anyInt(), any())).thenReturn(
new NetworkUpdateResult(0));
when(mWifiPermissionsUtil.checkSystemAlertWindowPermission(
Process.myUid(), TEST_PACKAGE_NAME)).thenReturn(true);
WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork();
mLooper.startAutoDispatch();
assertEquals(0, WifiConfigurationUtil.removeSecurityTypeFromNetworkId(
mWifiServiceImpl.addOrUpdateNetwork(config, TEST_PACKAGE_NAME)));
mLooper.stopAutoDispatchAndIgnoreExceptions();
verifyCheckChangePermission(TEST_PACKAGE_NAME);
verify(mWifiPermissionsUtil).checkSystemAlertWindowPermission(anyInt(), anyString());
verify(mWifiConfigManager).addOrUpdateNetwork(any(), anyInt(), any());
verify(mWifiMetrics).incrementNumAddOrUpdateNetworkCalls();
}
/**
* Verify that add or update networks is allowed for DeviceOwner app.
*/
@Test
public void testAddOrUpdateNetworkIsAllowedForDOApp() throws Exception {
doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManager)
.noteOp(AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Process.myUid(), TEST_PACKAGE_NAME);
when(mWifiPermissionsUtil.isDeviceOwner(Binder.getCallingUid(), TEST_PACKAGE_NAME))
.thenReturn(true);
when(mWifiConfigManager.addOrUpdateNetwork(any(), anyInt(), any())).thenReturn(
new NetworkUpdateResult(0));
WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork();
mLooper.startAutoDispatch();
assertEquals(0, WifiConfigurationUtil.removeSecurityTypeFromNetworkId(
mWifiServiceImpl.addOrUpdateNetwork(config, TEST_PACKAGE_NAME)));
mLooper.stopAutoDispatchAndIgnoreExceptions();
verifyCheckChangePermission(TEST_PACKAGE_NAME);
verify(mWifiConfigManager).addOrUpdateNetwork(any(), anyInt(), any());
verify(mWifiMetrics).incrementNumAddOrUpdateNetworkCalls();
}
/**
* Verify that add or update networks is allowed for ProfileOwner app.
*/
@Test
public void testAddOrUpdateNetworkIsAllowedForPOApp() throws Exception {
doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManager)
.noteOp(AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Process.myUid(), TEST_PACKAGE_NAME);
when(mWifiPermissionsUtil.isProfileOwner(Binder.getCallingUid(), TEST_PACKAGE_NAME))
.thenReturn(true);
when(mWifiConfigManager.addOrUpdateNetwork(any(), anyInt(), any())).thenReturn(
new NetworkUpdateResult(0));
WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork();
mLooper.startAutoDispatch();
assertEquals(0, WifiConfigurationUtil.removeSecurityTypeFromNetworkId(
mWifiServiceImpl.addOrUpdateNetwork(config, TEST_PACKAGE_NAME)));
mLooper.stopAutoDispatchAndIgnoreExceptions();
verifyCheckChangePermission(TEST_PACKAGE_NAME);
verify(mWifiConfigManager).addOrUpdateNetwork(any(), anyInt(), any());
verify(mWifiMetrics).incrementNumAddOrUpdateNetworkCalls();
}
private void verifyAddOrUpdateNetworkPrivilegedDoesNotThrowException() {
WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork();
when(mWifiConfigManager.addOrUpdateNetwork(any(), anyInt(), anyString()))
.thenReturn(new NetworkUpdateResult(0));
mLooper.startAutoDispatch();
mWifiServiceImpl.addOrUpdateNetworkPrivileged(config, TEST_PACKAGE_NAME);
mLooper.stopAutoDispatchAndIgnoreExceptions();
verify(mWifiConfigManager).addOrUpdateNetwork(any(), anyInt(), any());
verify(mWifiMetrics).incrementNumAddOrUpdateNetworkCalls();
}
/**
* Verify that addOrUpdateNetworkPrivileged throws a SecurityException if the calling app
* has no permissions.
*/
@Test
public void testAddOrUpdateNetworkPrivilegedNotAllowedForNormalApps() throws Exception {
try {
WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork();
mWifiServiceImpl.addOrUpdateNetworkPrivileged(config, TEST_PACKAGE_NAME);
fail("Expected SecurityException for apps without permission");
} catch (SecurityException e) {
}
}
/**
* Verify that a privileged app with NETWORK_SETTINGS permission is allowed to call
* addOrUpdateNetworkPrivileged.
*/
@Test
public void testAddOrUpdateNetworkPrivilegedIsAllowedForPrivilegedApp() throws Exception {
when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED);
verifyAddOrUpdateNetworkPrivilegedDoesNotThrowException();
}
/**
* Verify that a system app is allowed to call addOrUpdateNetworkPrivileged.
*/
@Test
public void testAddOrUpdateNetworkPrivilegedIsAllowedForSystemApp() throws Exception {
when(mWifiPermissionsUtil.isSystem(anyString(), anyInt())).thenReturn(true);
verifyAddOrUpdateNetworkPrivilegedDoesNotThrowException();
}
/**
* Verify that a Device Owner (DO) app is allowed to call addOrUpdateNetworkPrivileged.
*/
@Test
public void testAddOrUpdateNetworkPrivilegedIsAllowedForDOApp() throws Exception {
when(mWifiPermissionsUtil.isDeviceOwner(Binder.getCallingUid(), TEST_PACKAGE_NAME))
.thenReturn(true);
verifyAddOrUpdateNetworkPrivilegedDoesNotThrowException();
}
/**
* Verify that a Profile Owner (PO) app is allowed to call addOrUpdateNetworkPrivileged.
*/
@Test
public void testAddOrUpdateNetworkPrivilegedIsAllowedForPOApp() throws Exception {
when(mWifiPermissionsUtil.isProfileOwner(Binder.getCallingUid(), TEST_PACKAGE_NAME))
.thenReturn(true);
verifyAddOrUpdateNetworkPrivilegedDoesNotThrowException();
}
/**
* Verify the proper status code is returned when addOrUpdateNetworkPrivileged failed due to
* a failure in WifiConfigManager.addOrUpdateNetwork().
*/
@Test
public void testAddOrUpdateNetworkInvalidConfiguration() throws Exception {
when(mWifiPermissionsUtil.isSystem(anyString(), anyInt())).thenReturn(true);
when(mWifiConfigManager.addOrUpdateNetwork(any(), anyInt(), anyString()))
.thenReturn(new NetworkUpdateResult(-1));
WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork();
mLooper.startAutoDispatch();
WifiManager.AddNetworkResult result = mWifiServiceImpl.addOrUpdateNetworkPrivileged(
config, TEST_PACKAGE_NAME);
mLooper.stopAutoDispatchAndIgnoreExceptions();
assertEquals(WifiManager.AddNetworkResult.STATUS_ADD_WIFI_CONFIG_FAILURE,
result.statusCode);
assertEquals(-1, result.networkId);
}
/**
* Verify that enableNetwork is allowed for privileged Apps
*/
@Test
public void testEnableNetworkWithDisableOthersAllowedForPrivilegedApps() throws Exception {
when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED);
doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManager)
.noteOp(AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Process.myUid(), TEST_PACKAGE_NAME);
doAnswer(new AnswerWithArguments() {
public void answer(NetworkUpdateResult result, ActionListenerWrapper callback,
int callingUid) {
callback.sendSuccess(); // return success
}
}).when(mConnectHelper).connectToNetwork(
eq(new NetworkUpdateResult(TEST_NETWORK_ID)), any(), anyInt());
mLooper.startAutoDispatch();
assertTrue(mWifiServiceImpl.enableNetwork(TEST_NETWORK_ID, true, TEST_PACKAGE_NAME));
mLooper.stopAutoDispatch();
verify(mConnectHelper).connectToNetwork(
eq(new NetworkUpdateResult(TEST_NETWORK_ID)), any(), anyInt());
verify(mWifiMetrics).incrementNumEnableNetworkCalls();
}
/**
* Verify that enableNetwork (with disableOthers=true) is allowed for Apps targeting a SDK
* version less than Q
*/
@Test
public void testEnabledNetworkWithDisableOthersAllowedForAppsTargetingBelowQSdk()
throws Exception {
mLooper.dispatchAll();
doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManager)
.noteOp(AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Process.myUid(), TEST_PACKAGE_NAME);
when(mWifiPermissionsUtil.isTargetSdkLessThan(anyString(),
eq(Build.VERSION_CODES.Q), anyInt())).thenReturn(true);
doAnswer(new AnswerWithArguments() {
public void answer(NetworkUpdateResult result, ActionListenerWrapper callback,
int callingUid) {
callback.sendSuccess(); // return success
}
}).when(mConnectHelper).connectToNetwork(
eq(new NetworkUpdateResult(TEST_NETWORK_ID)), any(), anyInt());
mLooper.startAutoDispatch();
assertTrue(mWifiServiceImpl.enableNetwork(TEST_NETWORK_ID, true, TEST_PACKAGE_NAME));
mLooper.stopAutoDispatch();
verify(mConnectHelper).connectToNetwork(
eq(new NetworkUpdateResult(TEST_NETWORK_ID)), any(), anyInt());
verify(mWifiMetrics).incrementNumEnableNetworkCalls();
}
/**
* Verify that enableNetwork (with disableOthers=false) is allowed for Apps targeting a SDK
* version less than Q
*/
@Test
public void testEnabledNetworkWithoutDisableOthersAllowedForAppsTargetingBelowQSdk()
throws Exception {
mLooper.dispatchAll();
doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManager)
.noteOp(AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Process.myUid(), TEST_PACKAGE_NAME);
when(mWifiPermissionsUtil.isTargetSdkLessThan(anyString(),
eq(Build.VERSION_CODES.Q), anyInt())).thenReturn(true);
when(mWifiConfigManager.enableNetwork(anyInt(), anyBoolean(), anyInt(), anyString()))
.thenReturn(true);
mLooper.startAutoDispatch();
assertTrue(mWifiServiceImpl.enableNetwork(TEST_NETWORK_ID, false, TEST_PACKAGE_NAME));
mLooper.stopAutoDispatchAndIgnoreExceptions();
verify(mWifiConfigManager).enableNetwork(eq(TEST_NETWORK_ID), eq(false),
eq(Binder.getCallingUid()), eq(TEST_PACKAGE_NAME));
verify(mWifiMetrics).incrementNumEnableNetworkCalls();
}
/**
* Verify that enableNetwork is not allowed for Apps targeting Q SDK
*/
@Test
public void testEnableNetworkNotAllowedForAppsTargetingQ() throws Exception {
doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManager)
.noteOp(AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Process.myUid(), TEST_PACKAGE_NAME);
mLooper.startAutoDispatch();
mWifiServiceImpl.enableNetwork(TEST_NETWORK_ID, true, TEST_PACKAGE_NAME);
mLooper.stopAutoDispatchAndIgnoreExceptions();
verify(mConnectHelper, never()).connectToNetwork(any(), any(), anyInt());
verify(mWifiMetrics, never()).incrementNumEnableNetworkCalls();
}
/**
* Ensure that we invoke {@link WifiNetworkSuggestionsManager} to add network
* suggestions.
*/
@Test
public void testAddNetworkSuggestions() {
when(mWifiNetworkSuggestionsManager.add(any(), anyInt(), anyString(),
nullable(String.class))).thenReturn(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS);
mLooper.startAutoDispatch();
assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS,
mWifiServiceImpl.addNetworkSuggestions(mock(List.class), TEST_PACKAGE_NAME,
TEST_FEATURE_ID));
mLooper.stopAutoDispatchAndIgnoreExceptions();
when(mWifiNetworkSuggestionsManager.add(any(), anyInt(), anyString(),
nullable(String.class))).thenReturn(
WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_DUPLICATE);
mLooper.startAutoDispatch();
assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_DUPLICATE,
mWifiServiceImpl.addNetworkSuggestions(mock(List.class), TEST_PACKAGE_NAME,
TEST_FEATURE_ID));
mLooper.stopAutoDispatchAndIgnoreExceptions();
verify(mWifiNetworkSuggestionsManager, times(2)).add(
any(), eq(Binder.getCallingUid()), eq(TEST_PACKAGE_NAME), eq(TEST_FEATURE_ID));
}
/**
* Ensure that we don't invoke {@link WifiNetworkSuggestionsManager} to add network
* suggestions when the looper sync call times out.
*/
@Test
public void testAddNetworkSuggestionsFailureInRunWithScissors() {
mWifiServiceImpl = makeWifiServiceImplWithMockRunnerWhichTimesOut();
mLooper.startAutoDispatch();
assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_INTERNAL,
mWifiServiceImpl.addNetworkSuggestions(mock(List.class), TEST_PACKAGE_NAME,
TEST_FEATURE_ID));
mLooper.stopAutoDispatchAndIgnoreExceptions();
verify(mWifiNetworkSuggestionsManager, never()).add(any(), eq(Binder.getCallingUid()),
eq(TEST_PACKAGE_NAME), eq(TEST_FEATURE_ID));
}
/**
* Ensure that we invoke {@link WifiNetworkSuggestionsManager} to remove network
* suggestions.
*/
@Test
public void testRemoveNetworkSuggestions() {
when(mWifiNetworkSuggestionsManager.remove(any(), anyInt(), anyString()))
.thenReturn(WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_REMOVE_INVALID);
mLooper.startAutoDispatch();
assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_REMOVE_INVALID,
mWifiServiceImpl.removeNetworkSuggestions(mock(List.class), TEST_PACKAGE_NAME));
mLooper.stopAutoDispatchAndIgnoreExceptions();
when(mWifiNetworkSuggestionsManager.remove(any(), anyInt(), anyString()))
.thenReturn(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS);
mLooper.startAutoDispatch();
assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS,
mWifiServiceImpl.removeNetworkSuggestions(mock(List.class), TEST_PACKAGE_NAME));
mLooper.stopAutoDispatchAndIgnoreExceptions();
verify(mWifiNetworkSuggestionsManager, times(2)).remove(any(), anyInt(),
eq(TEST_PACKAGE_NAME));
}
/**
* Ensure that we don't invoke {@link WifiNetworkSuggestionsManager} to remove network
* suggestions when the looper sync call times out.
*/
@Test
public void testRemoveNetworkSuggestionsFailureInRunWithScissors() {
mWifiServiceImpl = makeWifiServiceImplWithMockRunnerWhichTimesOut();
mLooper.startAutoDispatch();
assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_INTERNAL,
mWifiServiceImpl.removeNetworkSuggestions(mock(List.class), TEST_PACKAGE_NAME));
mLooper.stopAutoDispatchAndIgnoreExceptions();
verify(mWifiNetworkSuggestionsManager, never()).remove(any(), anyInt(),
eq(TEST_PACKAGE_NAME));
}
@Test(expected = SecurityException.class)
public void testRemoveNonCallerConfiguredNetworks_NormalAppCaller_ThrowsException() {
mWifiServiceImpl.removeNonCallerConfiguredNetworks(TEST_PACKAGE_NAME);
}
@Test(expected = SecurityException.class)
public void testRemoveNonCallerConfiguredNetworks_CallerIsProfileOwner_ThrowsException() {
when(mWifiPermissionsUtil.isProfileOwner(Binder.getCallingUid(), TEST_PACKAGE_NAME))
.thenReturn(true);
mWifiServiceImpl.removeNonCallerConfiguredNetworks(TEST_PACKAGE_NAME);
}
@Test
public void testRemoveNonCallerConfiguredNetworks_NetworksRemoved() {
final int callerUid = Binder.getCallingUid();
when(mWifiPermissionsUtil.isDeviceOwner(Binder.getCallingUid(), TEST_PACKAGE_NAME))
.thenReturn(true);
mLooper.startAutoDispatch();
mWifiServiceImpl.removeNonCallerConfiguredNetworks(TEST_PACKAGE_NAME);
mLooper.stopAutoDispatchAndIgnoreExceptions();
verify(mWifiConfigManager).removeNonCallerConfiguredNetwork(eq(callerUid));
}
/**
* Ensure that we invoke {@link WifiNetworkSuggestionsManager} to get network
* suggestions.
*/
@Test
public void testGetNetworkSuggestions() {
List<WifiNetworkSuggestion> testList = new ArrayList<>();
when(mWifiNetworkSuggestionsManager.get(anyString(), anyInt())).thenReturn(testList);
mLooper.startAutoDispatch();
assertEquals(testList, mWifiServiceImpl.getNetworkSuggestions(TEST_PACKAGE_NAME));
mLooper.stopAutoDispatchAndIgnoreExceptions();
verify(mWifiNetworkSuggestionsManager).get(eq(TEST_PACKAGE_NAME), anyInt());
}
/**
* Ensure that we don't invoke {@link WifiNetworkSuggestionsManager} to get network
* suggestions when the looper sync call times out.
*/
@Test
public void testGetNetworkSuggestionsFailureInRunWithScissors() {
mWifiServiceImpl = makeWifiServiceImplWithMockRunnerWhichTimesOut();
mLooper.startAutoDispatch();
assertTrue(mWifiServiceImpl.getNetworkSuggestions(TEST_PACKAGE_NAME).isEmpty());
mLooper.stopAutoDispatchAndIgnoreExceptions();
verify(mWifiNetworkSuggestionsManager, never()).get(eq(TEST_PACKAGE_NAME), anyInt());
}
/**
* Verify that if the caller has NETWORK_SETTINGS permission, then it can invoke
* {@link WifiManager#disableEphemeralNetwork(String)}.
*/
@Test
public void testDisableEphemeralNetworkWithNetworkSettingsPerm() throws Exception {
when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED);
mWifiServiceImpl.disableEphemeralNetwork(new String(), TEST_PACKAGE_NAME);
mLooper.dispatchAll();
verify(mWifiConfigManager).userTemporarilyDisabledNetwork(anyString(), anyInt());
}
/**
* Verify that if the caller does not have NETWORK_SETTINGS permission, then it cannot invoke
* {@link WifiManager#disableEphemeralNetwork(String)}.
*/
@Test
public void testDisableEphemeralNetworkWithoutNetworkSettingsPerm() throws Exception {
when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_DENIED);
mWifiServiceImpl.disableEphemeralNetwork(new String(), TEST_PACKAGE_NAME);
mLooper.dispatchAll();
verify(mWifiConfigManager, never()).userTemporarilyDisabledNetwork(anyString(), anyInt());
}
/**
* Verify getting the factory MAC address.
*/
@Test
public void testGetFactoryMacAddresses() throws Exception {
when(mClientModeManager.getFactoryMacAddress()).thenReturn(TEST_FACTORY_MAC);
when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(true);
mLooper.startAutoDispatch();
final String[] factoryMacs = mWifiServiceImpl.getFactoryMacAddresses();
mLooper.stopAutoDispatchAndIgnoreExceptions();
assertEquals(1, factoryMacs.length);
assertEquals(TEST_FACTORY_MAC, factoryMacs[0]);
verify(mClientModeManager).getFactoryMacAddress();
}
/**
* Verify getting the factory MAC address returns null when posting the runnable to handler
* fails.
*/
@Test
public void testGetFactoryMacAddressesPostFail() throws Exception {
mWifiServiceImpl = makeWifiServiceImplWithMockRunnerWhichTimesOut();
when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(true);
mLooper.startAutoDispatch();
assertArrayEquals(new String[0], mWifiServiceImpl.getFactoryMacAddresses());
mLooper.stopAutoDispatchAndIgnoreExceptions();
verify(mClientModeManager, never()).getFactoryMacAddress();
}
/**
* Verify getting the factory MAC address returns null when the lower layers fail.
*/
@Test
public void testGetFactoryMacAddressesFail() throws Exception {
when(mClientModeManager.getFactoryMacAddress()).thenReturn(null);
when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(true);
mLooper.startAutoDispatch();
assertArrayEquals(new String[0], mWifiServiceImpl.getFactoryMacAddresses());
mLooper.stopAutoDispatchAndIgnoreExceptions();
verify(mClientModeManager).getFactoryMacAddress();
}
/**
* Verify getting the factory MAC address throws a SecurityException if the calling app
* doesn't have NETWORK_SETTINGS permission.
*/
@Test
public void testGetFactoryMacAddressesFailNoNetworkSettingsPermission() throws Exception {
when(mClientModeManager.getFactoryMacAddress()).thenReturn(TEST_FACTORY_MAC);
when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(false);
try {
mLooper.startAutoDispatch();
mWifiServiceImpl.getFactoryMacAddresses();
mLooper.stopAutoDispatchAndIgnoreExceptions();
fail();
} catch (SecurityException e) {
assertTrue("Exception message should contain 'factory MAC'",
e.toString().contains("factory MAC"));
}
}
/**
* Verify that a call to setDeviceMobilityState throws a SecurityException if the
* caller does not have WIFI_SET_DEVICE_MOBILITY_STATE permission.
*/
@Test(expected = SecurityException.class)
public void setDeviceMobilityStateThrowsSecurityExceptionOnMissingPermissions() {
doThrow(new SecurityException()).when(mContext)
.enforceCallingOrSelfPermission(
eq(android.Manifest.permission.WIFI_SET_DEVICE_MOBILITY_STATE),
eq("WifiService"));
mWifiServiceImpl.setDeviceMobilityState(DEVICE_MOBILITY_STATE_STATIONARY);
}
/**
* Verifies that setDeviceMobilityState runs on a separate handler thread.
*/
@Test
public void setDeviceMobilityStateRunsOnHandler() {
mWifiServiceImpl.setDeviceMobilityState(DEVICE_MOBILITY_STATE_STATIONARY);
verify(mWifiConnectivityManager, never())
.setDeviceMobilityState(DEVICE_MOBILITY_STATE_STATIONARY);
verify(mWifiHealthMonitor, never())
.setDeviceMobilityState(DEVICE_MOBILITY_STATE_STATIONARY);
verify(mWifiDataStall, never())
.setDeviceMobilityState(DEVICE_MOBILITY_STATE_STATIONARY);
mLooper.dispatchAll();
verify(mWifiConnectivityManager).setDeviceMobilityState(DEVICE_MOBILITY_STATE_STATIONARY);
verify(mWifiHealthMonitor).setDeviceMobilityState(DEVICE_MOBILITY_STATE_STATIONARY);
verify(mWifiDataStall).setDeviceMobilityState(DEVICE_MOBILITY_STATE_STATIONARY);
}
/**
* Verify that a call to addOnWifiUsabilityStatsListener throws a SecurityException if
* the caller does not have WIFI_UPDATE_USABILITY_STATS_SCORE permission.
*/
@Test
public void testAddStatsListenerThrowsSecurityExceptionOnMissingPermissions() {
doThrow(new SecurityException()).when(mContext)
.enforceCallingOrSelfPermission(
eq(android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE),
eq("WifiService"));
try {
mWifiServiceImpl.addOnWifiUsabilityStatsListener(mOnWifiUsabilityStatsListener);
fail("expected SecurityException");
} catch (SecurityException expected) {
}
}
/**
* Verify that a call to addOnWifiUsabilityStatsListener throws an IllegalArgumentException
* if the parameters are not provided.
*/
@Test
public void testAddStatsListenerThrowsIllegalArgumentExceptionOnInvalidArguments() {
try {
mWifiServiceImpl.addOnWifiUsabilityStatsListener(null);
fail("expected IllegalArgumentException");
} catch (IllegalArgumentException expected) {
}
}
/**
* Verify that a call to removeOnWifiUsabilityStatsListener throws a SecurityException if
* the caller does not have WIFI_UPDATE_USABILITY_STATS_SCORE permission.
*/
@Test
public void testRemoveStatsListenerThrowsSecurityExceptionOnMissingPermissions() {
doThrow(new SecurityException()).when(mContext)
.enforceCallingOrSelfPermission(
eq(android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE),
eq("WifiService"));
try {
mWifiServiceImpl.removeOnWifiUsabilityStatsListener(mOnWifiUsabilityStatsListener);
fail("expected SecurityException");
} catch (SecurityException expected) {
}
}
/**
* Verify that addOnWifiUsabilityStatsListener adds listener to {@link WifiMetrics}.
*/
@Test
public void testAddOnWifiUsabilityStatsListenerAndVerify() throws Exception {
mWifiServiceImpl.addOnWifiUsabilityStatsListener(mOnWifiUsabilityStatsListener);
mLooper.dispatchAll();
verify(mWifiMetrics).addOnWifiUsabilityListener(mOnWifiUsabilityStatsListener);
}
/**
* Verify that removeOnWifiUsabilityStatsListener removes listener from
* {@link WifiMetrics}.
*/
@Test
public void testRemoveOnWifiUsabilityStatsListenerAndVerify() throws Exception {
mWifiServiceImpl.removeOnWifiUsabilityStatsListener(mOnWifiUsabilityStatsListener);
mLooper.dispatchAll();
verify(mWifiMetrics).removeOnWifiUsabilityListener(mOnWifiUsabilityStatsListener);
}
/**
* Verify that a call to updateWifiUsabilityScore throws a SecurityException if the
* caller does not have UPDATE_WIFI_USABILITY_SCORE permission.
*/
@Test
public void testUpdateWifiUsabilityScoreThrowsSecurityExceptionOnMissingPermissions() {
doThrow(new SecurityException()).when(mContext)
.enforceCallingOrSelfPermission(
eq(android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE),
eq("WifiService"));
try {
mWifiServiceImpl.updateWifiUsabilityScore(anyInt(), anyInt(), 15);
fail("expected SecurityException");
} catch (SecurityException expected) {
}
}
/**
* Verify that mClientModeManager in WifiServiceImpl is being updated on Wifi usability score
* update event.
*/
@Test
public void testWifiUsabilityScoreUpdateAfterScoreEvent() {
mWifiServiceImpl.updateWifiUsabilityScore(5, 10, 15);
mLooper.dispatchAll();
verify(mWifiMetrics).incrementWifiUsabilityScoreCount(WIFI_IFACE_NAME, 5, 10, 15);
}
private void startLohsAndTethering(boolean isApConcurrencySupported) throws Exception {
// initialization
when(mActiveModeWarden.canRequestMoreSoftApManagers(
eq(new WorkSource(Binder.getCallingUid(), TEST_PACKAGE_NAME))))
.thenReturn(isApConcurrencySupported);
// For these tests, always use distinct interface names for LOHS and tethered.
mLohsInterfaceName = WIFI_IFACE_NAME2;
mLooper.startAutoDispatch();
setupLocalOnlyHotspot();
mLooper.stopAutoDispatchAndIgnoreExceptions();
reset(mActiveModeWarden);
when(mActiveModeWarden.canRequestMoreSoftApManagers(
eq(new WorkSource(Binder.getCallingUid(), TEST_PACKAGE_NAME))))
.thenReturn(isApConcurrencySupported);
// start tethering
mLooper.startAutoDispatch();
boolean tetheringResult = mWifiServiceImpl.startSoftAp(null, TEST_PACKAGE_NAME);
mLooper.stopAutoDispatchAndIgnoreExceptions();
assertTrue(tetheringResult);
verify(mActiveModeWarden).startSoftAp(any(),
eq(new WorkSource(Binder.getCallingUid(), TEST_PACKAGE_NAME)));
mWifiServiceImpl.updateInterfaceIpState(WIFI_IFACE_NAME, IFACE_IP_MODE_TETHERED);
mLooper.dispatchAll();
}
/**
* Verify LOHS gets stopped when trying to start tethering concurrently on devices that
* doesn't support dual AP operation.
*/
@Test
public void testStartLohsAndTethering1AP() throws Exception {
startLohsAndTethering(false);
// verify LOHS got stopped
verify(mLohsCallback).onHotspotFailed(anyInt());
verify(mActiveModeWarden).stopSoftAp(WifiManager.IFACE_IP_MODE_LOCAL_ONLY);
}
/**
* Verify LOHS doesn't get stopped when trying to start tethering concurrently on devices
* that does support dual AP operation.
*/
@Test
public void testStartLohsAndTethering2AP() throws Exception {
startLohsAndTethering(true);
// verify LOHS didn't get stopped
verifyZeroInteractions(ignoreStubs(mLohsCallback));
verify(mActiveModeWarden, never()).stopSoftAp(anyInt());
}
/**
* Verify that the call to startDppAsConfiguratorInitiator throws a security exception when the
* caller doesn't have NETWORK_SETTINGS permissions or NETWORK_SETUP_WIZARD.
*/
@Test(expected = SecurityException.class)
public void testStartDppAsConfiguratorInitiatorWithoutPermissions() {
mWifiServiceImpl.startDppAsConfiguratorInitiator(mAppBinder, TEST_PACKAGE_NAME, DPP_URI,
1, 1, mDppCallback);
}
/**
* Verify that the call to startDppAsEnrolleeInitiator throws a security exception when the
* caller doesn't have NETWORK_SETTINGS permissions or NETWORK_SETUP_WIZARD.
*/
@Test(expected = SecurityException.class)
public void testStartDppAsEnrolleeInitiatorWithoutPermissions() {
mWifiServiceImpl.startDppAsEnrolleeInitiator(mAppBinder, DPP_URI, mDppCallback);
}
/**
* Verify that the call to startDppAsEnrolleeResponder throws a security exception when the
* caller doesn't have NETWORK_SETTINGS permissions or NETWORK_SETUP_WIZARD.
*/
@Test(expected = SecurityException.class)
public void testStartDppAsEnrolleeResponderWithoutPermissions() {
assumeTrue(SdkLevel.isAtLeastS());
mWifiServiceImpl.startDppAsEnrolleeResponder(mAppBinder, DPP_PRODUCT_INFO,
EASY_CONNECT_CRYPTOGRAPHY_CURVE_PRIME256V1, mDppCallback);
}
/**
* Verify that a call to StartDppAsEnrolleeResponder throws an IllegalArgumentException
* if the deviceInfo length exceeds the max allowed length.
*/
@Test(expected = SecurityException.class)
public void testStartDppAsEnrolleeResponderThrowsIllegalArgumentExceptionOnDeviceInfoMaxLen() {
assumeTrue(SdkLevel.isAtLeastS());
try {
StringBuilder sb = new StringBuilder();
sb.append(Strings.repeat("a",
WifiManager.getEasyConnectMaxAllowedResponderDeviceInfoLength() + 2));
String deviceInfo = sb.toString();
mWifiServiceImpl.startDppAsEnrolleeResponder(mAppBinder, deviceInfo,
EASY_CONNECT_CRYPTOGRAPHY_CURVE_PRIME256V1, mDppCallback);
fail("expected IllegalArgumentException");
} catch (IllegalArgumentException expected) {
}
}
/**
* Verify that a call to StartDppAsEnrolleeResponder throws an IllegalArgumentException
* if the deviceInfo contains characters which are not allowed as per spec (For example
* semicolon)
*/
@Test(expected = SecurityException.class)
public void testStartDppAsEnrolleeResponderThrowsIllegalArgumentExceptionOnWrongDeviceInfo() {
assumeTrue(SdkLevel.isAtLeastS());
try {
mWifiServiceImpl.startDppAsEnrolleeResponder(mAppBinder, "DPP;TESTER",
EASY_CONNECT_CRYPTOGRAPHY_CURVE_PRIME256V1, mDppCallback);
fail("expected IllegalArgumentException");
} catch (IllegalArgumentException expected) {
}
}
/**
* Verify that the call to stopDppSession throws a security exception when the
* caller doesn't have NETWORK_SETTINGS permissions or NETWORK_SETUP_WIZARD.
*/
@Test(expected = SecurityException.class)
public void testStopDppSessionWithoutPermissions() {
try {
mWifiServiceImpl.stopDppSession();
} catch (RemoteException e) {
}
}
/**
* Verifies that configs can be removed.
*/
@Test
public void testRemoveNetworkIsAllowedForAppsTargetingBelowQSdk() {
doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManager)
.noteOp(AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Process.myUid(), TEST_PACKAGE_NAME);
when(mWifiConfigManager.removeNetwork(eq(0), anyInt(), anyString())).thenReturn(true);
when(mWifiPermissionsUtil.isTargetSdkLessThan(anyString(),
eq(Build.VERSION_CODES.Q), anyInt())).thenReturn(true);
mLooper.startAutoDispatch();
boolean result = mWifiServiceImpl.removeNetwork(0, TEST_PACKAGE_NAME);
mLooper.stopAutoDispatchAndIgnoreExceptions();
assertTrue(result);
verify(mWifiConfigManager).removeNetwork(anyInt(), anyInt(), anyString());
}
/**
* Verify that addOrUpdatePasspointConfiguration is allowed for apps targeting below R SDK.
*/
@Test
public void addOrUpdatePasspointConfigIsAllowedForAppsTargetingBelowRSdk() throws Exception {
doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManager)
.noteOp(AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Process.myUid(), TEST_PACKAGE_NAME);
when(mWifiPermissionsUtil.isTargetSdkLessThan(anyString(),
eq(Build.VERSION_CODES.R), anyInt())).thenReturn(true);
PasspointConfiguration config = new PasspointConfiguration();
HomeSp homeSp = new HomeSp();
homeSp.setFqdn("test.com");
config.setHomeSp(homeSp);
when(mPasspointManager.addOrUpdateProvider(
config, Binder.getCallingUid(), TEST_PACKAGE_NAME, false, true))
.thenReturn(true);
mLooper.startAutoDispatch();
assertTrue(mWifiServiceImpl.addOrUpdatePasspointConfiguration(config, TEST_PACKAGE_NAME));
mLooper.stopAutoDispatchAndIgnoreExceptions();
reset(mPasspointManager);
when(mPasspointManager.addOrUpdateProvider(
config, Binder.getCallingUid(), TEST_PACKAGE_NAME, false, true))
.thenReturn(false);
mLooper.startAutoDispatch();
assertFalse(mWifiServiceImpl.addOrUpdatePasspointConfiguration(config, TEST_PACKAGE_NAME));
mLooper.stopAutoDispatchAndIgnoreExceptions();
}
/**
* Verify that addOrUpdatePasspointConfiguration is not allowed for apps targeting R SDK.
*/
@Test
public void addOrUpdatePasspointConfigIsNotAllowedForAppsTargetingRSdk() throws Exception {
doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManager)
.noteOp(AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Process.myUid(), TEST_PACKAGE_NAME);
PasspointConfiguration config = new PasspointConfiguration();
HomeSp homeSp = new HomeSp();
homeSp.setFqdn("test.com");
config.setHomeSp(homeSp);
when(mPasspointManager.addOrUpdateProvider(
config, Binder.getCallingUid(), TEST_PACKAGE_NAME, false, true))
.thenReturn(true);
mLooper.startAutoDispatch();
assertFalse(mWifiServiceImpl.addOrUpdatePasspointConfiguration(config, TEST_PACKAGE_NAME));
mLooper.stopAutoDispatchAndIgnoreExceptions();
verify(mPasspointManager, never())
.addOrUpdateProvider(any(), anyInt(), anyString(), anyBoolean(), anyBoolean());
}
/**
* Verify that addOrUpdatePasspointConfiguration is allowed for Settings apps.
*/
@Test
public void addOrUpdatePasspointConfigIsAllowedSettingsApp() throws Exception {
when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED);
when(mWifiPermissionsUtil.isTargetSdkLessThan(anyString(),
eq(Build.VERSION_CODES.R), anyInt())).thenReturn(false);
PasspointConfiguration config = new PasspointConfiguration();
HomeSp homeSp = new HomeSp();
homeSp.setFqdn("test.com");
config.setHomeSp(homeSp);
when(mPasspointManager.addOrUpdateProvider(
config, Binder.getCallingUid(), TEST_PACKAGE_NAME, false, true))
.thenReturn(true);
mLooper.startAutoDispatch();
assertTrue(mWifiServiceImpl.addOrUpdatePasspointConfiguration(config, TEST_PACKAGE_NAME));
mLooper.stopAutoDispatchAndIgnoreExceptions();
verify(mPasspointManager).addOrUpdateProvider(any(), anyInt(), anyString(), anyBoolean(),
anyBoolean());
}
/**
* Verify that addOrUpdatePasspointConfiguration is allowed for System apps.
*/
@Test
public void addOrUpdatePasspointConfigIsAllowedSystemApp() throws Exception {
doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManager)
.noteOp(AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Process.myUid(), TEST_PACKAGE_NAME);
when(mWifiPermissionsUtil.isTargetSdkLessThan(anyString(),
eq(Build.VERSION_CODES.R), anyInt())).thenReturn(false);
when(mWifiPermissionsUtil.isSystem(anyString(), anyInt())).thenReturn(true);
PasspointConfiguration config = new PasspointConfiguration();
HomeSp homeSp = new HomeSp();
homeSp.setFqdn("test.com");
config.setHomeSp(homeSp);
when(mPasspointManager.addOrUpdateProvider(
config, Binder.getCallingUid(), TEST_PACKAGE_NAME, false, true))
.thenReturn(true);
mLooper.startAutoDispatch();
assertTrue(mWifiServiceImpl.addOrUpdatePasspointConfiguration(config, TEST_PACKAGE_NAME));
mLooper.stopAutoDispatchAndIgnoreExceptions();
verify(mPasspointManager).addOrUpdateProvider(any(), anyInt(), anyString(), anyBoolean(),
anyBoolean());
}
/**
* Verify that addOrUpdatePasspointConfiguration is allowed for DeviceOwner apps.
*/
@Test
public void addOrUpdatePasspointConfigIsAllowedSystemAlertDOApp() throws Exception {
doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManager)
.noteOp(AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Process.myUid(), TEST_PACKAGE_NAME);
when(mWifiPermissionsUtil.isTargetSdkLessThan(anyString(),
eq(Build.VERSION_CODES.R), anyInt())).thenReturn(false);
when(mWifiPermissionsUtil.isDeviceOwner(Binder.getCallingUid(), TEST_PACKAGE_NAME))
.thenReturn(true);
PasspointConfiguration config = new PasspointConfiguration();
HomeSp homeSp = new HomeSp();
homeSp.setFqdn("test.com");
config.setHomeSp(homeSp);
when(mPasspointManager.addOrUpdateProvider(
config, Binder.getCallingUid(), TEST_PACKAGE_NAME, false, true))
.thenReturn(true);
mLooper.startAutoDispatch();
assertTrue(mWifiServiceImpl.addOrUpdatePasspointConfiguration(config, TEST_PACKAGE_NAME));
mLooper.stopAutoDispatchAndIgnoreExceptions();
verify(mPasspointManager).addOrUpdateProvider(any(), anyInt(), anyString(), anyBoolean(),
anyBoolean());
}
/**
* Verify that addOrUpdatePasspointConfiguration is allowed for ProfileOwner apps.
*/
@Test
public void addOrUpdatePasspointConfigIsAllowedSystemAlertPOApp() throws Exception {
doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManager)
.noteOp(AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Process.myUid(), TEST_PACKAGE_NAME);
when(mWifiPermissionsUtil.isTargetSdkLessThan(anyString(),
eq(Build.VERSION_CODES.R), anyInt())).thenReturn(false);
when(mWifiPermissionsUtil.isProfileOwner(Binder.getCallingUid(), TEST_PACKAGE_NAME))
.thenReturn(true);
PasspointConfiguration config = new PasspointConfiguration();
HomeSp homeSp = new HomeSp();
homeSp.setFqdn("test.com");
config.setHomeSp(homeSp);
when(mPasspointManager.addOrUpdateProvider(
config, Binder.getCallingUid(), TEST_PACKAGE_NAME, false, true))
.thenReturn(true);
mLooper.startAutoDispatch();
assertTrue(mWifiServiceImpl.addOrUpdatePasspointConfiguration(config, TEST_PACKAGE_NAME));
mLooper.stopAutoDispatchAndIgnoreExceptions();
verify(mPasspointManager).addOrUpdateProvider(any(), anyInt(), anyString(), anyBoolean(),
anyBoolean());
}
/**
* Verify that removePasspointConfiguration will redirect calls to {@link PasspointManager}
* and returning the result that's returned from {@link PasspointManager}.
*/
@Test
public void removePasspointConfig() throws Exception {
when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(true);
String fqdn = "test.com";
when(mPasspointManager.removeProvider(anyInt(), anyBoolean(), isNull(), eq(fqdn)))
.thenReturn(true);
mLooper.startAutoDispatch();
assertTrue(mWifiServiceImpl.removePasspointConfiguration(fqdn, TEST_PACKAGE_NAME));
mLooper.stopAutoDispatchAndIgnoreExceptions();
reset(mPasspointManager);
when(mPasspointManager.removeProvider(anyInt(), anyBoolean(), isNull(), eq(fqdn)))
.thenReturn(false);
mLooper.startAutoDispatch();
assertFalse(mWifiServiceImpl.removePasspointConfiguration(fqdn, TEST_PACKAGE_NAME));
mLooper.stopAutoDispatchAndIgnoreExceptions();
}
/**
* Test that DISABLE_NETWORK returns failure to public API when WifiConfigManager returns
* failure.
*/
@Test
public void testDisableNetworkFailureAppBelowQSdk() throws Exception {
doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManager)
.noteOp(AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Process.myUid(), TEST_PACKAGE_NAME);
when(mWifiPermissionsUtil.isTargetSdkLessThan(anyString(),
eq(Build.VERSION_CODES.Q), anyInt())).thenReturn(true);
when(mWifiConfigManager.disableNetwork(anyInt(), anyInt(), anyString())).thenReturn(false);
mLooper.startAutoDispatch();
boolean succeeded = mWifiServiceImpl.disableNetwork(0, TEST_PACKAGE_NAME);
mLooper.stopAutoDispatchAndIgnoreExceptions();
assertFalse(succeeded);
}
@Test
public void testAllowAutojoinGlobalFailureNoNetworkSettingsPermission() throws Exception {
doThrow(new SecurityException()).when(mContext)
.enforceCallingOrSelfPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
eq("WifiService"));
try {
mWifiServiceImpl.allowAutojoinGlobal(true);
fail("Expected SecurityException");
} catch (SecurityException e) {
// Test succeeded
}
}
@Test
public void testAllowAutojoinFailureNoNetworkSettingsPermission() throws Exception {
doThrow(new SecurityException()).when(mContext)
.enforceCallingOrSelfPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
eq("WifiService"));
try {
mWifiServiceImpl.allowAutojoin(0, true);
fail("Expected SecurityException");
} catch (SecurityException e) {
// Test succeeded
}
}
@Test
public void testAllowAutojoinOnSuggestionNetwork() {
WifiConfiguration config = new WifiConfiguration();
config.allowAutojoin = false;
config.fromWifiNetworkSuggestion = true;
when(mWifiConfigManager.getConfiguredNetwork(anyInt())).thenReturn(config);
when(mWifiNetworkSuggestionsManager.allowNetworkSuggestionAutojoin(any(), anyBoolean()))
.thenReturn(true);
mWifiServiceImpl.allowAutojoin(0, true);
mLooper.dispatchAll();
verify(mWifiConfigManager).getConfiguredNetwork(0);
verify(mWifiNetworkSuggestionsManager).allowNetworkSuggestionAutojoin(any(), anyBoolean());
verify(mWifiConfigManager).allowAutojoin(anyInt(), anyBoolean());
verify(mWifiMetrics).logUserActionEvent(eq(UserActionEvent.EVENT_CONFIGURE_AUTO_CONNECT_ON),
anyInt());
}
@Test
public void testAllowAutojoinOnSavedNetwork() {
WifiConfiguration config = new WifiConfiguration();
config.allowAutojoin = false;
config.fromWifiNetworkSuggestion = false;
config.fromWifiNetworkSpecifier = false;
when(mWifiConfigManager.getConfiguredNetwork(0)).thenReturn(config);
mWifiServiceImpl.allowAutojoin(0, true);
mLooper.dispatchAll();
verify(mWifiConfigManager).getConfiguredNetwork(0);
verify(mWifiNetworkSuggestionsManager, never())
.allowNetworkSuggestionAutojoin(any(), anyBoolean());
verify(mWifiConfigManager).allowAutojoin(anyInt(), anyBoolean());
}
@Test
public void testAllowAutojoinOnWifiNetworkSpecifier() {
WifiConfiguration config = new WifiConfiguration();
config.fromWifiNetworkSpecifier = true;
when(mWifiConfigManager.getConfiguredNetwork(0)).thenReturn(config);
mWifiServiceImpl.allowAutojoin(0, true);
mLooper.dispatchAll();
verify(mWifiConfigManager).getConfiguredNetwork(0);
verify(mWifiNetworkSuggestionsManager, never())
.allowNetworkSuggestionAutojoin(config, true);
verify(mWifiConfigManager, never()).allowAutojoin(0, true);
}
@Test
public void testAllowAutojoinOnSavedPasspointNetwork() {
WifiConfiguration config = WifiConfigurationTestUtil.createPasspointNetwork();
when(mWifiConfigManager.getConfiguredNetwork(0)).thenReturn(config);
when(mWifiNetworkSuggestionsManager.allowNetworkSuggestionAutojoin(any(), anyBoolean()))
.thenReturn(true);
mWifiServiceImpl.allowAutojoin(0, true);
mLooper.dispatchAll();
verify(mWifiConfigManager).getConfiguredNetwork(0);
verify(mWifiNetworkSuggestionsManager, never())
.allowNetworkSuggestionAutojoin(config, true);
verify(mWifiConfigManager, never()).allowAutojoin(0, true);
}
/**
* Test that setMacRandomizationSettingPasspointEnabled is protected by NETWORK_SETTINGS
* permission.
*/
@Test
public void testSetMacRandomizationSettingPasspointEnabledFailureNoNetworkSettingsPermission()
throws Exception {
doThrow(new SecurityException()).when(mContext)
.enforceCallingOrSelfPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
eq("WifiService"));
try {
mWifiServiceImpl.setMacRandomizationSettingPasspointEnabled("TEST_FQDN", true);
fail("Expected SecurityException");
} catch (SecurityException e) {
// Test succeeded
}
}
/**
* Test that setMacRandomizationSettingPasspointEnabled makes the appropriate calls.
*/
@Test
public void testSetMacRandomizationSettingPasspointEnabled() throws Exception {
mWifiServiceImpl.setMacRandomizationSettingPasspointEnabled("TEST_FQDN", true);
mLooper.dispatchAll();
verify(mPasspointManager).enableMacRandomization("TEST_FQDN", true);
}
/**
* Test that setPasspointMeteredOverride is protected by NETWORK_SETTINGS permission.
*/
@Test
public void testSetPasspointMeteredOverrideFailureNoNetworkSettingsPermission()
throws Exception {
doThrow(new SecurityException()).when(mContext)
.enforceCallingOrSelfPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
eq("WifiService"));
try {
mWifiServiceImpl.setPasspointMeteredOverride("TEST_FQDN", METERED_OVERRIDE_METERED);
fail("Expected SecurityException");
} catch (SecurityException e) {
// Test succeeded
}
}
/**
* Test that setPasspointMeteredOverride makes the appropriate calls.
*/
@Test
public void testSetPasspointMeteredOverride() throws Exception {
mWifiServiceImpl.setPasspointMeteredOverride("TEST_FQDN", METERED_OVERRIDE_METERED);
mLooper.dispatchAll();
verify(mPasspointManager).setMeteredOverride("TEST_FQDN", METERED_OVERRIDE_METERED);
}
/**
* Test handle boot completed sequence.
*/
@Test
public void testHandleBootCompleted() throws Exception {
when(mWifiInjector.getPasspointProvisionerHandlerThread())
.thenReturn(mock(HandlerThread.class));
mLooper.startAutoDispatch();
mWifiServiceImpl.handleBootCompleted();
mLooper.stopAutoDispatch();
verify(mWifiNetworkFactory).register();
verify(mUntrustedWifiNetworkFactory).register();
verify(mPasspointManager).initializeProvisioner(any());
verify(mWifiP2pConnection).handleBootCompleted();
verify(mWifiCountryCode).registerListener(any(WifiCountryCode.ChangeListener.class));
}
/**
* Test handle user switch sequence.
*/
@Test
public void testHandleUserSwitch() throws Exception {
mWifiServiceImpl.handleUserSwitch(5);
mLooper.dispatchAll();
verify(mWifiConfigManager).handleUserSwitch(5);
verify(mWifiNotificationManager).createNotificationChannels();
verify(mWifiNetworkSuggestionsManager).resetNotification();
verify(mWifiCarrierInfoManager).resetNotification();
verify(mOpenNetworkNotifier).clearPendingNotification(false);
verify(mWakeupController).resetNotification();
}
/**
* Test handle user unlock sequence.
*/
@Test
public void testHandleUserUnlock() throws Exception {
mWifiServiceImpl.handleUserUnlock(5);
mLooper.dispatchAll();
verify(mWifiConfigManager).handleUserUnlock(5);
}
/**
* Test handle user stop sequence.
*/
@Test
public void testHandleUserStop() throws Exception {
mWifiServiceImpl.handleUserStop(5);
mLooper.dispatchAll();
verify(mWifiConfigManager).handleUserStop(5);
}
/**
* Test register scan result callback without permission.
*/
@Test(expected = SecurityException.class)
public void testRegisterScanResultCallbackWithMissingPermission() throws Exception {
doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission(
eq(ACCESS_WIFI_STATE), eq("WifiService"));
mWifiServiceImpl.registerScanResultsCallback(mScanResultsCallback);
}
/**
* Test unregister scan result callback without permission.
*/
@Test(expected = SecurityException.class)
public void testUnregisterScanResultCallbackWithMissingPermission() throws Exception {
doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission(
eq(ACCESS_WIFI_STATE), eq("WifiService"));
mWifiServiceImpl.unregisterScanResultsCallback(mScanResultsCallback);
}
/**
* Test register scan result callback with illegal argument.
*/
@Test(expected = IllegalArgumentException.class)
public void testRegisterScanResultCallbackWithIllegalArgument() throws Exception {
mWifiServiceImpl.registerScanResultsCallback(null);
}
/**
* Test register and unregister callback will go to ScanRequestProxy;
*/
@Test
public void testRegisterUnregisterScanResultCallback() throws Exception {
mWifiServiceImpl.registerScanResultsCallback(mScanResultsCallback);
mLooper.dispatchAll();
verify(mScanRequestProxy).registerScanResultsCallback(mScanResultsCallback);
mWifiServiceImpl.unregisterScanResultsCallback(mScanResultsCallback);
mLooper.dispatchAll();
verify(mScanRequestProxy).unregisterScanResultsCallback(mScanResultsCallback);
}
/**
* Test register callback without permission.
*/
@Test(expected = SecurityException.class)
public void testRegisterSuggestionNetworkCallbackWithMissingPermission() {
doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission(
eq(ACCESS_WIFI_STATE), eq("WifiService"));
mWifiServiceImpl.registerSuggestionConnectionStatusListener(
mSuggestionConnectionStatusListener, TEST_PACKAGE_NAME, TEST_FEATURE_ID);
}
/**
* Test register callback without callback
*/
@Test(expected = IllegalArgumentException.class)
public void testRegisterSuggestionNetworkCallbackWithIllegalArgument() {
mWifiServiceImpl.registerSuggestionConnectionStatusListener(null, TEST_PACKAGE_NAME,
TEST_FEATURE_ID);
}
/**
* Test unregister callback without permission.
*/
@Test(expected = SecurityException.class)
public void testUnregisterSuggestionNetworkCallbackWithMissingPermission() {
doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission(
eq(ACCESS_WIFI_STATE), eq("WifiService"));
mWifiServiceImpl.unregisterSuggestionConnectionStatusListener(
mSuggestionConnectionStatusListener, TEST_PACKAGE_NAME);
}
/**
* Test register nad unregister callback will go to WifiNetworkSuggestionManager
*/
@Test
public void testRegisterUnregisterSuggestionNetworkCallback() throws Exception {
mWifiServiceImpl.registerSuggestionConnectionStatusListener(
mSuggestionConnectionStatusListener, TEST_PACKAGE_NAME, TEST_FEATURE_ID);
mLooper.dispatchAll();
verify(mWifiNetworkSuggestionsManager).registerSuggestionConnectionStatusListener(
eq(mSuggestionConnectionStatusListener), eq(TEST_PACKAGE_NAME), anyInt());
mWifiServiceImpl.unregisterSuggestionConnectionStatusListener(
mSuggestionConnectionStatusListener, TEST_PACKAGE_NAME);
mLooper.dispatchAll();
verify(mWifiNetworkSuggestionsManager).unregisterSuggestionConnectionStatusListener(
eq(mSuggestionConnectionStatusListener), eq(TEST_PACKAGE_NAME), anyInt());
}
/**
* Test to verify that the lock mode is verified before dispatching the operation
*
* Steps: call acquireWifiLock with an invalid lock mode.
* Expected: the call should throw an IllegalArgumentException.
*/
@Test(expected = IllegalArgumentException.class)
public void acquireWifiLockShouldThrowExceptionOnInvalidLockMode() throws Exception {
final int wifiLockModeInvalid = -1;
mWifiServiceImpl.acquireWifiLock(mAppBinder, wifiLockModeInvalid, "", null);
}
private void setupReportActivityInfo() {
WifiLinkLayerStats stats = new WifiLinkLayerStats();
stats.on_time = 1000;
stats.tx_time = 1;
stats.rx_time = 2;
stats.tx_time_per_level = new int[] {3, 4, 5};
stats.on_time_scan = 6;
when(mClientModeManager.getWifiLinkLayerStats()).thenReturn(stats);
when(mPowerProfile.getAveragePower(PowerProfile.POWER_WIFI_CONTROLLER_IDLE))
.thenReturn(7.0);
when(mPowerProfile.getAveragePower(PowerProfile.POWER_WIFI_CONTROLLER_RX))
.thenReturn(8.0);
when(mPowerProfile.getAveragePower(PowerProfile.POWER_WIFI_CONTROLLER_TX))
.thenReturn(9.0);
when(mPowerProfile.getAveragePower(PowerProfile.POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE))
.thenReturn(10000.0);
when(mClock.getElapsedSinceBootMillis()).thenReturn(9999L);
}
private void validateWifiActivityEnergyInfo(WifiActivityEnergyInfo info) {
assertNotNull(info);
assertEquals(9999L, info.getTimeSinceBootMillis());
assertEquals(WifiActivityEnergyInfo.STACK_STATE_STATE_IDLE, info.getStackState());
assertEquals(1, info.getControllerTxDurationMillis());
assertEquals(2, info.getControllerRxDurationMillis());
assertEquals(6, info.getControllerScanDurationMillis());
assertEquals(997, info.getControllerIdleDurationMillis());
}
/**
* Tests that {@link WifiServiceImpl#getWifiActivityEnergyInfoAsync} throws
* {@link SecurityException} if the caller doesn't have the necessary permissions.
*/
@Test(expected = SecurityException.class)
public void getWifiActivityEnergyInfoAsyncNoPermission() throws Exception {
doThrow(SecurityException.class)
.when(mContext).enforceCallingOrSelfPermission(eq(ACCESS_WIFI_STATE), any());
mWifiServiceImpl.getWifiActivityEnergyInfoAsync(mOnWifiActivityEnergyInfoListener);
}
/**
* Tests that {@link WifiServiceImpl#getWifiActivityEnergyInfoAsync} passes null to the listener
* if link layer stats is unsupported.
*/
@Test
public void getWifiActivityEnergyInfoAsyncFeatureUnsupported() throws Exception {
when(mClientModeManager.getSupportedFeatures()).thenReturn(0L);
mLooper.startAutoDispatch();
mWifiServiceImpl.getWifiActivityEnergyInfoAsync(mOnWifiActivityEnergyInfoListener);
mLooper.stopAutoDispatch();
verify(mOnWifiActivityEnergyInfoListener).onWifiActivityEnergyInfo(null);
}
/**
* Tests that {@link WifiServiceImpl#getWifiActivityEnergyInfoAsync} passes the expected values
* to the listener on success.
*/
@Test
public void getWifiActivityEnergyInfoAsyncSuccess() throws Exception {
when(mClientModeManager.getSupportedFeatures()).thenReturn(Long.MAX_VALUE);
setupReportActivityInfo();
mLooper.startAutoDispatch();
mWifiServiceImpl.getWifiActivityEnergyInfoAsync(mOnWifiActivityEnergyInfoListener);
mLooper.stopAutoDispatch();
ArgumentCaptor<WifiActivityEnergyInfo> infoCaptor =
ArgumentCaptor.forClass(WifiActivityEnergyInfo.class);
verify(mOnWifiActivityEnergyInfoListener).onWifiActivityEnergyInfo(infoCaptor.capture());
validateWifiActivityEnergyInfo(infoCaptor.getValue());
}
@Test
public void testCarrierConfigChangeUpdateSoftApCapability() throws Exception {
MockitoSession staticMockSession = mockitoSession()
.mockStatic(SubscriptionManager.class)
.startMocking();
lenient().when(SubscriptionManager.getActiveDataSubscriptionId())
.thenReturn(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID);
mWifiServiceImpl.checkAndStartWifi();
mLooper.dispatchAll();
verify(mContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
argThat((IntentFilter filter) ->
filter.hasAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED)));
// Send the broadcast
Intent intent = new Intent(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
mBroadcastReceiverCaptor.getValue().onReceive(mContext, intent);
mLooper.dispatchAll();
verify(mActiveModeWarden).updateSoftApCapability(any());
staticMockSession.finishMocking();
}
@Test
public void testPhoneActiveDataSubscriptionIdChangedUpdateSoftApCapability() throws Exception {
MockitoSession staticMockSession = mockitoSession()
.mockStatic(SubscriptionManager.class)
.startMocking();
lenient().when(SubscriptionManager.getActiveDataSubscriptionId())
.thenReturn(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID);
mWifiServiceImpl.checkAndStartWifi();
mLooper.dispatchAll();
verify(mContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
argThat((IntentFilter filter) ->
filter.hasAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED)));
ArgumentCaptor<PhoneStateListener> phoneStateListenerCaptor =
ArgumentCaptor.forClass(PhoneStateListener.class);
verify(mTelephonyManager).listen(phoneStateListenerCaptor.capture(),
eq(PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE));
mPhoneStateListener = phoneStateListenerCaptor.getValue();
assertNotNull(mPhoneStateListener);
mPhoneStateListener.onActiveDataSubscriptionIdChanged(2);
mLooper.dispatchAll();
verify(mActiveModeWarden).updateSoftApCapability(any());
staticMockSession.finishMocking();
}
/**
* Verify that the call to getWifiConfigsForMatchedNetworkSuggestions is not redirected to
* specific API getWifiConfigForMatchedNetworkSuggestionsSharedWithUser when the caller doesn't
* have NETWORK_SETTINGS permissions and NETWORK_SETUP_WIZARD.
*/
@Test(expected = SecurityException.class)
public void testGetWifiConfigsForMatchedNetworkSuggestionsWithoutPermissions() {
mWifiServiceImpl.getWifiConfigForMatchedNetworkSuggestionsSharedWithUser(new ArrayList<>());
}
/**
* Verify that the call to getWifiConfigsForMatchedNetworkSuggestions is redirected to
* specific API getWifiConfigForMatchedNetworkSuggestionsSharedWithUser when the caller
* have NETWORK_SETTINGS.
*/
@Test
public void testGetWifiConfigsForMatchedNetworkSuggestionsWithSettingPermissions() {
when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED);
mLooper.startAutoDispatch();
mWifiServiceImpl
.getWifiConfigForMatchedNetworkSuggestionsSharedWithUser(createScanResultList());
mLooper.stopAutoDispatch();
verify(mWifiNetworkSuggestionsManager)
.getWifiConfigForMatchedNetworkSuggestionsSharedWithUser(any());
}
/**
* Verify that the call to getWifiConfigsForMatchedNetworkSuggestions is redirected to
* specific API getWifiConfigForMatchedNetworkSuggestionsSharedWithUser when the caller
* have NETWORK_SETUP_WIZARD.
*/
@Test
public void testGetWifiConfigsForMatchedNetworkSuggestionsWithSetupWizardPermissions() {
when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETUP_WIZARD),
anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED);
mLooper.startAutoDispatch();
mWifiServiceImpl
.getWifiConfigForMatchedNetworkSuggestionsSharedWithUser(createScanResultList());
mLooper.stopAutoDispatch();
verify(mWifiNetworkSuggestionsManager)
.getWifiConfigForMatchedNetworkSuggestionsSharedWithUser(any());
}
@Test
public void testGetWifiConfigsForMatchedNetworkSuggestionsWithInvalidScanResults() {
when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED);
mWifiServiceImpl
.getWifiConfigForMatchedNetworkSuggestionsSharedWithUser(new ArrayList<>());
mLooper.dispatchAll();
verify(mWifiNetworkSuggestionsManager, never())
.getWifiConfigForMatchedNetworkSuggestionsSharedWithUser(any());
}
/**
* Verify that a call to setWifiConnectedNetworkScorer throws a SecurityException if
* the caller does not have WIFI_UPDATE_USABILITY_STATS_SCORE permission.
*/
@Test
public void testSetNetworkScorerThrowsSecurityExceptionOnMissingPermissions() {
doThrow(new SecurityException()).when(mContext)
.enforceCallingOrSelfPermission(
eq(android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE),
eq("WifiService"));
try {
mWifiServiceImpl.setWifiConnectedNetworkScorer(mAppBinder, mWifiConnectedNetworkScorer);
fail("expected SecurityException");
} catch (SecurityException expected) {
}
}
/**
* Verify that a call to setWifiConnectedNetworkScorer throws an IllegalArgumentException
* if the parameters are not provided.
*/
@Test
public void testSetScorerThrowsIllegalArgumentExceptionOnInvalidArguments() {
try {
mWifiServiceImpl.setWifiConnectedNetworkScorer(mAppBinder, null);
fail("expected IllegalArgumentException");
} catch (IllegalArgumentException expected) {
}
}
/**
* Verify that a call to clearWifiConnectedNetworkScorer throws a SecurityException if
* the caller does not have WIFI_UPDATE_USABILITY_STATS_SCORE permission.
*/
@Test
public void testClearNetworkScorerThrowsSecurityExceptionOnMissingPermissions() {
doThrow(new SecurityException()).when(mContext)
.enforceCallingOrSelfPermission(
eq(android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE),
eq("WifiService"));
try {
mWifiServiceImpl.clearWifiConnectedNetworkScorer();
fail("expected SecurityException");
} catch (SecurityException expected) {
}
}
/**
* Verify that setWifiConnectedNetworkScorer sets scorer to {@link WifiScoreReport}.
*/
@Test
public void testSetWifiConnectedNetworkScorerAndVerify() throws Exception {
mLooper.startAutoDispatch();
mWifiServiceImpl.setWifiConnectedNetworkScorer(mAppBinder, mWifiConnectedNetworkScorer);
mLooper.stopAutoDispatch();
verify(mActiveModeWarden).setWifiConnectedNetworkScorer(
mAppBinder, mWifiConnectedNetworkScorer);
}
/**
* Verify that clearWifiConnectedNetworkScorer clears scorer from {@link WifiScoreReport}.
*/
@Test
public void testClearWifiConnectedNetworkScorerAndVerify() throws Exception {
mWifiServiceImpl.clearWifiConnectedNetworkScorer();
mLooper.dispatchAll();
verify(mActiveModeWarden).clearWifiConnectedNetworkScorer();
}
private long testGetSupportedFeaturesCaseForRtt(
long supportedFeaturesFromClientModeManager, boolean rttDisabled) {
when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_WIFI_RTT)).thenReturn(
!rttDisabled);
when(mClientModeManager.getSupportedFeatures())
.thenReturn(supportedFeaturesFromClientModeManager);
mLooper.startAutoDispatch();
long supportedFeatures = mWifiServiceImpl.getSupportedFeatures();
mLooper.stopAutoDispatchAndIgnoreExceptions();
return supportedFeatures;
}
/** Verifies that syncGetSupportedFeatures() masks out capabilities based on system flags. */
@Test
public void syncGetSupportedFeaturesForRtt() {
final long featureAware = WifiManager.WIFI_FEATURE_AWARE;
final long featureInfra = WifiManager.WIFI_FEATURE_INFRA;
final long featureD2dRtt = WifiManager.WIFI_FEATURE_D2D_RTT;
final long featureD2apRtt = WifiManager.WIFI_FEATURE_D2AP_RTT;
final long featureLongBits = 0x1000000000L;
assertEquals(0, testGetSupportedFeaturesCaseForRtt(0, false));
assertEquals(0, testGetSupportedFeaturesCaseForRtt(0, true));
assertEquals(featureAware | featureInfra,
testGetSupportedFeaturesCaseForRtt(featureAware | featureInfra, false));
assertEquals(featureAware | featureInfra,
testGetSupportedFeaturesCaseForRtt(featureAware | featureInfra, true));
assertEquals(featureInfra | featureD2dRtt,
testGetSupportedFeaturesCaseForRtt(featureInfra | featureD2dRtt, false));
assertEquals(featureInfra,
testGetSupportedFeaturesCaseForRtt(featureInfra | featureD2dRtt, true));
assertEquals(featureInfra | featureD2apRtt,
testGetSupportedFeaturesCaseForRtt(featureInfra | featureD2apRtt, false));
assertEquals(featureInfra,
testGetSupportedFeaturesCaseForRtt(featureInfra | featureD2apRtt, true));
assertEquals(featureInfra | featureD2dRtt | featureD2apRtt,
testGetSupportedFeaturesCaseForRtt(
featureInfra | featureD2dRtt | featureD2apRtt, false));
assertEquals(featureInfra,
testGetSupportedFeaturesCaseForRtt(
featureInfra | featureD2dRtt | featureD2apRtt, true));
assertEquals(featureLongBits | featureInfra | featureD2dRtt | featureD2apRtt,
testGetSupportedFeaturesCaseForRtt(
featureLongBits | featureInfra | featureD2dRtt | featureD2apRtt, false));
assertEquals(featureLongBits | featureInfra,
testGetSupportedFeaturesCaseForRtt(
featureLongBits | featureInfra | featureD2dRtt | featureD2apRtt, true));
}
private long testGetSupportedFeaturesCaseForMacRandomization(
long supportedFeaturesFromClientModeManager, boolean apMacRandomizationEnabled,
boolean staConnectedMacRandomizationEnabled, boolean p2pMacRandomizationEnabled) {
when(mResources.getBoolean(
R.bool.config_wifi_connected_mac_randomization_supported))
.thenReturn(staConnectedMacRandomizationEnabled);
when(mResources.getBoolean(
R.bool.config_wifi_ap_mac_randomization_supported))
.thenReturn(apMacRandomizationEnabled);
when(mResources.getBoolean(
R.bool.config_wifi_p2p_mac_randomization_supported))
.thenReturn(p2pMacRandomizationEnabled);
when(mClientModeManager.getSupportedFeatures())
.thenReturn(supportedFeaturesFromClientModeManager);
mLooper.startAutoDispatch();
long supportedFeatures = mWifiServiceImpl.getSupportedFeatures();
mLooper.stopAutoDispatchAndIgnoreExceptions();
return supportedFeatures;
}
/** Verifies that syncGetSupportedFeatures() masks out capabilities based on system flags. */
@Test
public void syncGetSupportedFeaturesForMacRandomization() {
final long featureStaConnectedMacRandomization =
WifiManager.WIFI_FEATURE_CONNECTED_RAND_MAC;
final long featureApMacRandomization =
WifiManager.WIFI_FEATURE_AP_RAND_MAC;
final long featureP2pMacRandomization =
WifiManager.WIFI_FEATURE_CONNECTED_RAND_MAC;
assertEquals(featureStaConnectedMacRandomization | featureApMacRandomization
| featureP2pMacRandomization,
testGetSupportedFeaturesCaseForMacRandomization(
featureP2pMacRandomization, true, true, true));
// p2p supported by HAL, but disabled by overlay.
assertEquals(featureStaConnectedMacRandomization | featureApMacRandomization,
testGetSupportedFeaturesCaseForMacRandomization(
featureP2pMacRandomization, true, true, false));
assertEquals(featureStaConnectedMacRandomization | featureApMacRandomization,
testGetSupportedFeaturesCaseForMacRandomization(0, true, true, false));
}
@Test
public void getSupportedFeaturesVerboseLoggingThrottled() {
mWifiServiceImpl.enableVerboseLogging(
WifiManager.VERBOSE_LOGGING_LEVEL_ENABLED); // this logs
when(mClock.getElapsedSinceBootMillis()).thenReturn(1000L);
testGetSupportedFeaturesCaseForMacRandomization(0, true, true, false);
when(mClock.getElapsedSinceBootMillis()).thenReturn(1001L);
testGetSupportedFeaturesCaseForMacRandomization(0, true, true, false); // should not log
when(mClock.getElapsedSinceBootMillis()).thenReturn(5000L);
testGetSupportedFeaturesCaseForMacRandomization(0, true, true, false);
testGetSupportedFeaturesCaseForMacRandomization(0, true, false, false);
verify(mLog, times(4)).info(any());
}
/**
* Verifies that syncGetSupportedFeatures() adds capabilities based on interface
* combination.
*/
@Test
public void syncGetSupportedFeaturesForStaApConcurrency() {
long supportedFeaturesFromClientModeManager = WifiManager.WIFI_FEATURE_OWE;
when(mClientModeManager.getSupportedFeatures())
.thenReturn(supportedFeaturesFromClientModeManager);
when(mActiveModeWarden.isStaApConcurrencySupported())
.thenReturn(false);
mLooper.startAutoDispatch();
assertEquals(supportedFeaturesFromClientModeManager,
mWifiServiceImpl.getSupportedFeatures());
mLooper.stopAutoDispatchAndIgnoreExceptions();
when(mActiveModeWarden.isStaApConcurrencySupported())
.thenReturn(true);
mLooper.startAutoDispatch();
assertEquals(supportedFeaturesFromClientModeManager | WifiManager.WIFI_FEATURE_AP_STA,
mWifiServiceImpl.getSupportedFeatures());
mLooper.stopAutoDispatchAndIgnoreExceptions();
}
/**
* Verify startRestrictingAutoJoinToSubscriptionId is guarded by NETWORK_SETTINGS
* permission.
*/
@Test
public void testStartTemporarilyDisablingAllNonCarrierMergedWifiPermission() {
assumeTrue(SdkLevel.isAtLeastS());
when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_DENIED);
when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETUP_WIZARD),
anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_DENIED);
try {
mWifiServiceImpl.startRestrictingAutoJoinToSubscriptionId(1);
fail();
} catch (SecurityException e) {
// pass
}
}
/**
* Verify startRestrictingAutoJoinToSubscriptionId works properly with permission.
*/
@Test
public void testStartTemporarilyDisablingAllNonCarrierMergedWifi() {
assumeTrue(SdkLevel.isAtLeastS());
when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETUP_WIZARD),
anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED);
mWifiServiceImpl.startRestrictingAutoJoinToSubscriptionId(1);
mLooper.dispatchAll();
verify(mWifiConfigManager).startRestrictingAutoJoinToSubscriptionId(1);
verify(mClientModeManager).disconnect();
}
/**
* Verify stopRestrictingAutoJoinToSubscriptionId is guarded by NETWORK_SETTINGS
* and NETWORK_SETUP_WIZARD permission.
*/
@Test
public void testStopTemporarilyDisablingAllNonCarrierMergedWifiPermission() {
assumeTrue(SdkLevel.isAtLeastS());
when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_DENIED);
when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETUP_WIZARD),
anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_DENIED);
try {
mWifiServiceImpl.stopRestrictingAutoJoinToSubscriptionId();
fail();
} catch (SecurityException e) {
// pass
}
}
/**
* Verify stopRestrictingAutoJoinToSubscriptionId works properly with permission.
*/
@Test
public void testStopTemporarilyDisablingAllNonCarrierMergedWifi() {
assumeTrue(SdkLevel.isAtLeastS());
when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED);
mWifiServiceImpl.stopRestrictingAutoJoinToSubscriptionId();
mLooper.dispatchAll();
verify(mWifiConfigManager).stopRestrictingAutoJoinToSubscriptionId();
}
/**
* Verifies that syncGetSupportedFeatures() adds capabilities based on interface
* combination.
*/
@Test
public void syncGetSupportedFeaturesForStaStaConcurrency() {
assumeTrue(SdkLevel.isAtLeastS());
long supportedFeaturesFromClientModeManager = WifiManager.WIFI_FEATURE_OWE;
when(mClientModeManager.getSupportedFeatures())
.thenReturn(supportedFeaturesFromClientModeManager);
mLooper.startAutoDispatch();
assertEquals(supportedFeaturesFromClientModeManager,
mWifiServiceImpl.getSupportedFeatures());
mLooper.stopAutoDispatchAndIgnoreExceptions();
when(mActiveModeWarden.isStaStaConcurrencySupportedForLocalOnlyConnections())
.thenReturn(true);
mLooper.startAutoDispatch();
assertEquals(supportedFeaturesFromClientModeManager
| WifiManager.WIFI_FEATURE_ADDITIONAL_STA_LOCAL_ONLY,
mWifiServiceImpl.getSupportedFeatures());
mLooper.stopAutoDispatchAndIgnoreExceptions();
when(mActiveModeWarden.isStaStaConcurrencySupportedForMbb()).thenReturn(true);
mLooper.startAutoDispatch();
assertEquals(supportedFeaturesFromClientModeManager
| WifiManager.WIFI_FEATURE_ADDITIONAL_STA_LOCAL_ONLY
| WifiManager.WIFI_FEATURE_ADDITIONAL_STA_MBB,
mWifiServiceImpl.getSupportedFeatures());
mLooper.stopAutoDispatchAndIgnoreExceptions();
when(mActiveModeWarden.isStaStaConcurrencySupportedForRestrictedConnections())
.thenReturn(true);
mLooper.startAutoDispatch();
assertEquals(supportedFeaturesFromClientModeManager
| WifiManager.WIFI_FEATURE_ADDITIONAL_STA_LOCAL_ONLY
| WifiManager.WIFI_FEATURE_ADDITIONAL_STA_MBB
| WifiManager.WIFI_FEATURE_ADDITIONAL_STA_RESTRICTED,
mWifiServiceImpl.getSupportedFeatures());
mLooper.stopAutoDispatchAndIgnoreExceptions();
}
@Test
public void testSetScanThrottleEnabledWithNetworkSettingsPermission() {
doNothing().when(mContext)
.enforceCallingOrSelfPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
eq("WifiService"));
mWifiServiceImpl.setScanThrottleEnabled(true);
mLooper.dispatchAll();
verify(mScanRequestProxy).setScanThrottleEnabled(true);
mWifiServiceImpl.setScanThrottleEnabled(false);
mLooper.dispatchAll();
verify(mScanRequestProxy).setScanThrottleEnabled(false);
}
@Test(expected = SecurityException.class)
public void testSetScanThrottleEnabledWithNoNetworkSettingsPermission() {
doThrow(new SecurityException()).when(mContext)
.enforceCallingOrSelfPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
eq("WifiService"));
mWifiServiceImpl.setScanThrottleEnabled(true);
mLooper.dispatchAll();
verify(mScanRequestProxy, never()).setScanThrottleEnabled(true);
}
@Test
public void testIsScanThrottleEnabled() {
when(mScanRequestProxy.isScanThrottleEnabled()).thenReturn(true);
mLooper.startAutoDispatch();
assertTrue(mWifiServiceImpl.isScanThrottleEnabled());
mLooper.stopAutoDispatchAndIgnoreExceptions();
verify(mScanRequestProxy).isScanThrottleEnabled();
}
@Test
public void testSetAutoWakeupEnabledWithNetworkSettingsPermission() {
doNothing().when(mContext)
.enforceCallingOrSelfPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
eq("WifiService"));
mWifiServiceImpl.setAutoWakeupEnabled(true);
mLooper.dispatchAll();
verify(mWakeupController).setEnabled(true);
mWifiServiceImpl.setAutoWakeupEnabled(false);
mLooper.dispatchAll();
verify(mWakeupController).setEnabled(false);
}
@Test(expected = SecurityException.class)
public void testSetAutoWakeupEnabledWithNoNetworkSettingsPermission() {
doThrow(new SecurityException()).when(mContext)
.enforceCallingOrSelfPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
eq("WifiService"));
mWifiServiceImpl.setAutoWakeupEnabled(true);
mLooper.dispatchAll();
verify(mWakeupController, never()).setEnabled(true);
}
@Test
public void testIsAutoWakeupEnabled() {
when(mWakeupController.isEnabled()).thenReturn(true);
mLooper.startAutoDispatch();
assertTrue(mWifiServiceImpl.isAutoWakeupEnabled());
mLooper.stopAutoDispatchAndIgnoreExceptions();
verify(mWakeupController).isEnabled();
}
@Test
public void testSetScanAlwaysAvailableWithNetworkSettingsPermission() {
doNothing().when(mContext)
.enforceCallingOrSelfPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
eq("WifiService"));
mWifiServiceImpl.setScanAlwaysAvailable(true, TEST_PACKAGE_NAME);
verify(mSettingsStore).handleWifiScanAlwaysAvailableToggled(true);
verify(mActiveModeWarden).scanAlwaysModeChanged();
mWifiServiceImpl.setScanAlwaysAvailable(false, TEST_PACKAGE_NAME);
verify(mSettingsStore).handleWifiScanAlwaysAvailableToggled(false);
verify(mActiveModeWarden, times(2)).scanAlwaysModeChanged();
}
@Test(expected = SecurityException.class)
public void testSetScanAlwaysAvailableWithNoNetworkSettingsPermission() {
doThrow(new SecurityException()).when(mContext)
.enforceCallingOrSelfPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
eq("WifiService"));
mWifiServiceImpl.setScanAlwaysAvailable(true, TEST_PACKAGE_NAME);
verify(mSettingsStore, never()).handleWifiScanAlwaysAvailableToggled(anyBoolean());
verify(mActiveModeWarden, never()).scanAlwaysModeChanged();
}
@Test
public void testIsScanAlwaysAvailable() {
when(mSettingsStore.isScanAlwaysAvailableToggleEnabled()).thenReturn(true);
assertTrue(mWifiServiceImpl.isScanAlwaysAvailable());
verify(mSettingsStore).isScanAlwaysAvailableToggleEnabled();
}
private List<ScanResult> createScanResultList() {
return Collections.singletonList(new ScanResult(WifiSsid.createFromAsciiEncoded(TEST_SSID),
TEST_SSID, TEST_BSSID, 1245, 0, TEST_CAP, -78, 2450, 1025, 22, 33, 20, 0, 0, true));
}
private void sendCountryCodeChangedBroadcast(String countryCode) {
Intent intent = new Intent(TelephonyManager.ACTION_NETWORK_COUNTRY_CHANGED);
intent.putExtra(TelephonyManager.EXTRA_NETWORK_COUNTRY, countryCode);
assertNotNull(mBroadcastReceiverCaptor.getValue());
mBroadcastReceiverCaptor.getValue().onReceive(mContext, intent);
}
@Test
public void testCountryCodeBroadcastHanding() {
mWifiServiceImpl.checkAndStartWifi();
mLooper.dispatchAll();
verify(mContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
argThat((IntentFilter filter) ->
filter.hasAction(TelephonyManager.ACTION_NETWORK_COUNTRY_CHANGED)));
sendCountryCodeChangedBroadcast("US");
verify(mWifiCountryCode).setTelephonyCountryCodeAndUpdate(any());
}
@Test
public void testDumpShouldDumpWakeupController() {
mLooper.startAutoDispatch();
mWifiServiceImpl.dump(new FileDescriptor(), new PrintWriter(new StringWriter()), null);
mLooper.stopAutoDispatchAndIgnoreExceptions();
verify(mWakeupController).dump(any(), any(), any());
}
/**
* Test register listener without permission.
*/
@Test(expected = SecurityException.class)
public void testAddSuggestionUserApprovalStatusListenerWithMissingPermission() {
doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission(
eq(ACCESS_WIFI_STATE), eq("WifiService"));
mWifiServiceImpl.addSuggestionUserApprovalStatusListener(
mSuggestionUserApprovalStatusListener, TEST_PACKAGE_NAME);
}
/**
* Test register listener from background user.
*/
@Test(expected = SecurityException.class)
public void testAddSuggestionUserApprovalStatusListenerFromBackgroundUser() {
when(mWifiPermissionsUtil.doesUidBelongToCurrentUser(anyInt())).thenReturn(false);
mWifiServiceImpl.addSuggestionUserApprovalStatusListener(
mSuggestionUserApprovalStatusListener, TEST_PACKAGE_NAME);
}
/**
* Test unregister listener from background user.
*/
@Test(expected = SecurityException.class)
public void testRemoveSuggestionUserApprovalStatusListenerFromBackgroundUser() {
when(mWifiPermissionsUtil.doesUidBelongToCurrentUser(anyInt())).thenReturn(false);
mWifiServiceImpl.removeSuggestionUserApprovalStatusListener(
mSuggestionUserApprovalStatusListener, TEST_PACKAGE_NAME);
}
/**
* Test register listener without listener
*/
@Test(expected = NullPointerException.class)
public void testAddSuggestionUserApprovalStatusListenerWithIllegalArgument() {
mWifiServiceImpl.addSuggestionUserApprovalStatusListener(null, TEST_PACKAGE_NAME);
}
/**
* Test unregister callback without permission.
*/
@Test(expected = SecurityException.class)
public void testUnregisterSuggestionUserApprovalStatusListenerWithMissingPermission() {
doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission(
eq(ACCESS_WIFI_STATE), eq("WifiService"));
mWifiServiceImpl.removeSuggestionUserApprovalStatusListener(
mSuggestionUserApprovalStatusListener, TEST_PACKAGE_NAME);
}
/**
* Test add and remove listener will go to WifiNetworkSuggestionManager
*/
@Test
public void testAddRemoveSuggestionUserApprovalStatusListener() {
mWifiServiceImpl.addSuggestionUserApprovalStatusListener(
mSuggestionUserApprovalStatusListener, TEST_PACKAGE_NAME);
mLooper.dispatchAll();
verify(mWifiNetworkSuggestionsManager).addSuggestionUserApprovalStatusListener(
eq(mSuggestionUserApprovalStatusListener), eq(TEST_PACKAGE_NAME), anyInt());
mWifiServiceImpl.removeSuggestionUserApprovalStatusListener(
mSuggestionUserApprovalStatusListener, TEST_PACKAGE_NAME);
mLooper.dispatchAll();
verify(mWifiNetworkSuggestionsManager).removeSuggestionUserApprovalStatusListener(
eq(mSuggestionUserApprovalStatusListener), eq(TEST_PACKAGE_NAME), anyInt());
}
@Test
public void testGetDhcpInfo() throws Exception {
DhcpResultsParcelable dhcpResultsParcelable = new DhcpResultsParcelable();
dhcpResultsParcelable.leaseDuration = 100;
when(mClientModeManager.syncGetDhcpResultsParcelable()).thenReturn(dhcpResultsParcelable);
mLooper.startAutoDispatch();
DhcpInfo dhcpInfo = mWifiServiceImpl.getDhcpInfo(TEST_PACKAGE);
mLooper.stopAutoDispatchAndIgnoreExceptions();
assertEquals(dhcpResultsParcelable.leaseDuration, dhcpInfo.leaseDuration);
}
@Test
public void testGetDhcpInfoFromSecondaryCmmFromAppRequestingSecondaryCmm() throws Exception {
DhcpResultsParcelable dhcpResultsParcelable = new DhcpResultsParcelable();
dhcpResultsParcelable.leaseDuration = 100;
ConcreteClientModeManager secondaryCmm = mock(ConcreteClientModeManager.class);
when(secondaryCmm.getRequestorWs())
.thenReturn(new WorkSource(Binder.getCallingUid(), TEST_PACKAGE));
when(secondaryCmm.syncGetDhcpResultsParcelable()).thenReturn(dhcpResultsParcelable);
when(mActiveModeWarden.getClientModeManagersInRoles(
ROLE_CLIENT_LOCAL_ONLY, ROLE_CLIENT_SECONDARY_LONG_LIVED))
.thenReturn(Arrays.asList(secondaryCmm));
mLooper.startAutoDispatch();
DhcpInfo dhcpInfo = mWifiServiceImpl.getDhcpInfo(TEST_PACKAGE);
mLooper.stopAutoDispatchAndIgnoreExceptions();
assertEquals(dhcpResultsParcelable.leaseDuration, dhcpInfo.leaseDuration);
}
@Test
public void testGetDhcpInfoFromPrimaryCmmFromAppNotRequestingSecondaryCmm() throws Exception {
DhcpResultsParcelable dhcpResultsParcelable = new DhcpResultsParcelable();
dhcpResultsParcelable.leaseDuration = 100;
when(mClientModeManager.syncGetDhcpResultsParcelable()).thenReturn(dhcpResultsParcelable);
ConcreteClientModeManager secondaryCmm = mock(ConcreteClientModeManager.class);
when(secondaryCmm.getRequestorWs())
.thenReturn(new WorkSource(Binder.getCallingUid(), TEST_PACKAGE_NAME_OTHER));
when(mActiveModeWarden.getClientModeManagersInRoles(
ROLE_CLIENT_LOCAL_ONLY, ROLE_CLIENT_SECONDARY_LONG_LIVED))
.thenReturn(Arrays.asList(secondaryCmm));
mLooper.startAutoDispatch();
DhcpInfo dhcpInfo = mWifiServiceImpl.getDhcpInfo(TEST_PACKAGE);
mLooper.stopAutoDispatchAndIgnoreExceptions();
assertEquals(dhcpResultsParcelable.leaseDuration, dhcpInfo.leaseDuration);
}
@Test
public void testSetEmergencyScanRequestInProgress() throws Exception {
mWifiServiceImpl.setEmergencyScanRequestInProgress(true);
verify(mActiveModeWarden).setEmergencyScanRequestInProgress(true);
mWifiServiceImpl.setEmergencyScanRequestInProgress(false);
verify(mActiveModeWarden).setEmergencyScanRequestInProgress(false);
}
@Test
public void testSetEmergencyScanRequestWithoutPermissionThrowsException() throws Exception {
when(mContext.checkCallingOrSelfPermission(android.Manifest.permission.NETWORK_STACK))
.thenReturn(PackageManager.PERMISSION_DENIED);
doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission(
eq(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK), any());
try {
mWifiServiceImpl.setEmergencyScanRequestInProgress(true);
fail();
} catch (SecurityException e) { }
}
@Test
public void testRemoveAppState() throws Exception {
mWifiServiceImpl.removeAppState(TEST_UID, TEST_PACKAGE_NAME);
mLooper.dispatchAll();
verify(mScanRequestProxy).clearScanRequestTimestampsForApp(TEST_PACKAGE_NAME, TEST_UID);
verify(mWifiNetworkSuggestionsManager).removeApp(TEST_PACKAGE_NAME);
verify(mWifiNetworkFactory).removeUserApprovedAccessPointsForApp(TEST_PACKAGE_NAME);
verify(mPasspointManager).removePasspointProviderWithPackage(TEST_PACKAGE_NAME);
}
@Test
public void testRemoveAppStateWithoutPermissionThrowsException() throws Exception {
doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission(
eq(Manifest.permission.NETWORK_SETTINGS), any());
try {
mWifiServiceImpl.removeAppState(TEST_UID, TEST_PACKAGE_NAME);
fail();
} catch (SecurityException e) { }
}
@Test
public void testNotificationResetWithLocaleChange() {
mWifiServiceImpl.checkAndStartWifi();
mLooper.dispatchAll();
verify(mContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
argThat((IntentFilter filter) ->
filter.hasAction(Intent.ACTION_LOCALE_CHANGED)));
verify(mWifiNotificationManager).createNotificationChannels();
clearInvocations(mWifiNotificationManager);
Intent intent = new Intent(Intent.ACTION_LOCALE_CHANGED);
mBroadcastReceiverCaptor.getValue().onReceive(mContext, intent);
verify(mWifiNotificationManager).createNotificationChannels();
verify(mWifiNetworkSuggestionsManager).resetNotification();
verify(mWifiCarrierInfoManager).resetNotification();
verify(mOpenNetworkNotifier).clearPendingNotification(false);
verify(mWakeupController).resetNotification();
}
/**
* Verify that a call to setWifiScoringEnabled throws a SecurityException if the caller does
* not have NETWORK_SETTINGS permission.
*/
@Test
public void testSetWifiScoringEnabledThrowsSecurityExceptionOnMissingPermissions() {
doThrow(new SecurityException()).when(mContext)
.enforceCallingOrSelfPermission(
eq(android.Manifest.permission.NETWORK_SETTINGS),
eq("WifiService"));
try {
mWifiServiceImpl.setWifiScoringEnabled(true);
fail("expected SecurityException");
} catch (SecurityException expected) {
}
}
/**
* Verify that setWifiScoringEnabled sets the boolean to {@link WifiSettingsStore}.
*/
@Test
public void testSetWifiScoringEnabledGoesToSettingsStore() {
mLooper.startAutoDispatch();
mWifiServiceImpl.setWifiScoringEnabled(true);
mLooper.stopAutoDispatch();
verify(mSettingsStore).handleWifiScoringEnabled(true);
}
@Test
public void testEnabledTdlsWithMacAddress() {
mWifiServiceImpl.enableTdlsWithMacAddress(TEST_BSSID, true);
mLooper.dispatchAll();
verify(mClientModeManager).enableTdls(TEST_BSSID, true);
mWifiServiceImpl.enableTdlsWithMacAddress(TEST_BSSID, false);
mLooper.dispatchAll();
verify(mClientModeManager).enableTdls(TEST_BSSID, false);
}
/**
* Verify that a call to setOverrideCountryCode() throws a SecurityException if the caller does
* not have the MANAGE_WIFI_COUNTRY_CODE permission.
*/
@Test
public void testSetOverrideCountryCodeThrowsSecurityExceptionOnMissingPermissions() {
assumeTrue(SdkLevel.isAtLeastS());
doThrow(new SecurityException()).when(mContext)
.enforceCallingOrSelfPermission(eq(MANAGE_WIFI_COUNTRY_CODE),
eq("WifiService"));
try {
mWifiServiceImpl.setOverrideCountryCode(TEST_COUNTRY_CODE);
fail("expected SecurityException");
} catch (SecurityException expected) { }
}
/**
* Verify the call to setOverrideCountryCode() goes to WifiCountryCode
*/
@Test
public void testSetOverrideCountryCode() throws Exception {
assumeTrue(SdkLevel.isAtLeastS());
mWifiServiceImpl.setOverrideCountryCode(TEST_COUNTRY_CODE);
mLooper.dispatchAll();
verify(mWifiCountryCode).setOverrideCountryCode(TEST_COUNTRY_CODE);
}
/**
* Verify that a call to clearOverrideCountryCode() throws a SecurityException if the caller
* does not have the MANAGE_WIFI_COUNTRY_CODE permission.
*/
@Test
public void testClearOverrideCountryCodeThrowsSecurityExceptionOnMissingPermissions() {
assumeTrue(SdkLevel.isAtLeastS());
doThrow(new SecurityException()).when(mContext)
.enforceCallingOrSelfPermission(eq(MANAGE_WIFI_COUNTRY_CODE),
eq("WifiService"));
try {
mWifiServiceImpl.clearOverrideCountryCode();
fail("expected SecurityException");
} catch (SecurityException expected) { }
}
/**
* Verify the call to clearOverrideCountryCode() goes to WifiCountryCode
*/
@Test
public void testClearOverrideCountryCode() throws Exception {
assumeTrue(SdkLevel.isAtLeastS());
mWifiServiceImpl.clearOverrideCountryCode();
mLooper.dispatchAll();
verify(mWifiCountryCode).clearOverrideCountryCode();
}
/**
* Verify that a call to setDefaultCountryCode() throws a SecurityException if the caller does
* not have the MANAGE_WIFI_COUNTRY_CODE permission.
*/
@Test
public void testSetDefaultCountryCodeThrowsSecurityExceptionOnMissingPermissions() {
assumeTrue(SdkLevel.isAtLeastS());
doThrow(new SecurityException()).when(mContext)
.enforceCallingOrSelfPermission(eq(MANAGE_WIFI_COUNTRY_CODE),
eq("WifiService"));
try {
mWifiServiceImpl.setDefaultCountryCode(TEST_COUNTRY_CODE);
fail("expected SecurityException");
} catch (SecurityException expected) { }
}
/**
* Verify the call to setDefaultCountryCode() goes to WifiCountryCode
*/
@Test
public void testSetDefaultCountryCode() throws Exception {
assumeTrue(SdkLevel.isAtLeastS());
mWifiServiceImpl.setDefaultCountryCode(TEST_COUNTRY_CODE);
mLooper.dispatchAll();
verify(mWifiCountryCode).setDefaultCountryCode(TEST_COUNTRY_CODE);
}
/**
* Verify that a call to flushPasspointAnqpCache throws a SecurityException if the
* caller does not have any permission.
*/
@Test (expected = SecurityException.class)
public void testFlushPasspointAnqpCacheThrowsSecurityExceptionOnMissingPermissions() {
when(mContext.checkCallingOrSelfPermission(anyString()))
.thenReturn(PackageManager.PERMISSION_DENIED);
when(mWifiPermissionsUtil.isDeviceOwner(anyInt(), anyString())).thenReturn(false);
when(mWifiPermissionsUtil.isProfileOwner(anyInt(), anyString())).thenReturn(false);
mWifiServiceImpl.flushPasspointAnqpCache(mContext.getPackageName());
}
/**
* Verifies that the call to testFlushPasspointAnqpCache with DO permission calls Passpoint
* manager to flush the ANQP cache and clear all pending requests.
*/
@Test
public void testFlushPasspointAnqpCacheWithDoPermissions() {
when(mContext.checkCallingOrSelfPermission(anyString()))
.thenReturn(PackageManager.PERMISSION_DENIED);
when(mWifiPermissionsUtil.isDeviceOwner(anyInt(), eq(TEST_PACKAGE_NAME))).thenReturn(true);
when(mWifiPermissionsUtil.isProfileOwner(anyInt(),
eq(TEST_PACKAGE_NAME))).thenReturn(false);
mWifiServiceImpl.flushPasspointAnqpCache(TEST_PACKAGE_NAME);
mLooper.dispatchAll();
verify(mPasspointManager).clearAnqpRequestsAndFlushCache();
}
/**
* Verifies that the call to testFlushPasspointAnqpCache with PO permission calls Passpoint
* manager to flush the ANQP cache and clear all pending requests.
*/
@Test
public void testFlushPasspointAnqpCacheWithPoPermissions() {
when(mContext.checkCallingOrSelfPermission(anyString()))
.thenReturn(PackageManager.PERMISSION_DENIED);
when(mWifiPermissionsUtil.isDeviceOwner(anyInt(), eq(TEST_PACKAGE_NAME))).thenReturn(false);
when(mWifiPermissionsUtil.isProfileOwner(anyInt(), eq(TEST_PACKAGE_NAME))).thenReturn(true);
mWifiServiceImpl.flushPasspointAnqpCache(TEST_PACKAGE_NAME);
mLooper.dispatchAll();
verify(mPasspointManager).clearAnqpRequestsAndFlushCache();
}
/**
* Verifies that the call to testFlushPasspointAnqpCache calls Passpoint manager to flush the
* ANQP cache and clear all pending requests.
*/
@Test
public void testFlushPasspointAnqpCache() {
when(mContext.checkCallingOrSelfPermission(android.Manifest.permission.NETWORK_SETTINGS))
.thenReturn(PackageManager.PERMISSION_GRANTED);
when(mWifiPermissionsUtil.isDeviceOwner(anyInt(), eq(TEST_PACKAGE_NAME))).thenReturn(false);
when(mWifiPermissionsUtil.isProfileOwner(anyInt(),
eq(TEST_PACKAGE_NAME))).thenReturn(false);
mWifiServiceImpl.flushPasspointAnqpCache(TEST_PACKAGE_NAME);
mLooper.dispatchAll();
verify(mPasspointManager).clearAnqpRequestsAndFlushCache();
}
/**
* Verify that a call to getUsableChannels() throws a SecurityException if the caller does
* not have the LOCATION_HARDWARE permission.
*/
@Test
public void testGetUsableChannelsThrowsSecurityExceptionOnMissingPermissions() {
assumeTrue(SdkLevel.isAtLeastS());
when(mWifiPermissionsUtil.isLocationModeEnabled()).thenReturn(true);
doThrow(new SecurityException()).when(mWifiPermissionsUtil)
.checkCallersHardwareLocationPermission(anyInt());
try {
mWifiServiceImpl.getUsableChannels(WIFI_BAND_24_GHZ, OP_MODE_STA, FILTER_REGULATORY);
fail("expected SecurityException");
} catch (SecurityException expected) { }
}
/**
* Verify the call to isValidBandForGetUsableChannels()
*/
@Test
public void testIsValidBandForGetUsableChannels() throws Exception {
assumeTrue(SdkLevel.isAtLeastS());
assertEquals(WifiServiceImpl.isValidBandForGetUsableChannels(
WifiScanner.WIFI_BAND_UNSPECIFIED), true);
assertEquals(WifiServiceImpl.isValidBandForGetUsableChannels(
WifiScanner.WIFI_BAND_24_GHZ), true);
assertEquals(WifiServiceImpl.isValidBandForGetUsableChannels(
WifiScanner.WIFI_BAND_5_GHZ), false);
assertEquals(WifiServiceImpl.isValidBandForGetUsableChannels(
WifiScanner.WIFI_BAND_BOTH), false);
assertEquals(WifiServiceImpl.isValidBandForGetUsableChannels(
WifiScanner.WIFI_BAND_5_GHZ_DFS_ONLY), false);
assertEquals(WifiServiceImpl.isValidBandForGetUsableChannels(
WifiScanner.WIFI_BAND_24_GHZ_WITH_5GHZ_DFS), false);
assertEquals(WifiServiceImpl.isValidBandForGetUsableChannels(
WifiScanner.WIFI_BAND_5_GHZ_WITH_DFS), true);
assertEquals(WifiServiceImpl.isValidBandForGetUsableChannels(
WifiScanner.WIFI_BAND_BOTH_WITH_DFS), true);
assertEquals(WifiServiceImpl.isValidBandForGetUsableChannels(
WifiScanner.WIFI_BAND_6_GHZ), true);
assertEquals(WifiServiceImpl.isValidBandForGetUsableChannels(
WifiScanner.WIFI_BAND_24_5_6_GHZ), false);
assertEquals(WifiServiceImpl.isValidBandForGetUsableChannels(
WifiScanner.WIFI_BAND_24_5_WITH_DFS_6_GHZ), true);
assertEquals(WifiServiceImpl.isValidBandForGetUsableChannels(
WifiScanner.WIFI_BAND_60_GHZ), true);
assertEquals(WifiServiceImpl.isValidBandForGetUsableChannels(
WifiScanner.WIFI_BAND_24_5_6_60_GHZ), false);
assertEquals(WifiServiceImpl.isValidBandForGetUsableChannels(
WifiScanner.WIFI_BAND_24_5_WITH_DFS_6_60_GHZ), true);
}
/**
* Verify that a call to getUsableChannels() throws an IllegalArgumentException
* if the band specified is invalid for getAllowedChannels() method.
*/
@Test
public void testGetUsableChannelsThrowsIllegalArgumentExceptionOnInValidBand() {
assumeTrue(SdkLevel.isAtLeastS());
when(mWifiPermissionsUtil.isLocationModeEnabled()).thenReturn(true);
when(mWifiPermissionsUtil.checkCallersHardwareLocationPermission(anyInt()))
.thenReturn(true);
try {
mWifiServiceImpl.getUsableChannels(WIFI_BAND_5_GHZ, OP_MODE_STA, FILTER_REGULATORY);
fail("expected IllegalArgumentException");
} catch (IllegalArgumentException expected) {
}
}
/**
* Verify the call to getUsableChannels() goes to WifiNative
*/
@Test
public void testGetUsableChannels() throws Exception {
assumeTrue(SdkLevel.isAtLeastS());
when(mWifiPermissionsUtil.isLocationModeEnabled()).thenReturn(true);
when(mWifiPermissionsUtil.checkCallersHardwareLocationPermission(anyInt()))
.thenReturn(true);
mLooper.startAutoDispatch();
mWifiServiceImpl.getUsableChannels(WIFI_BAND_24_GHZ, OP_MODE_STA, FILTER_REGULATORY);
mLooper.stopAutoDispatch();
verify(mWifiNative).getUsableChannels(anyInt(), anyInt(), anyInt());
}
/**
* Verify that if the caller has NETWORK_SETTINGS permission, and the overlay
* config_wifiAllowInsecureEnterpriseConfigurationsForSettingsAndSUW is set, then it can add an
* insecure Enterprise network, with Root CA certificate not set and/or domain name not set.
*/
@Test
public void testAddInsecureEnterpirseNetworkWithNetworkSettingsPerm() throws Exception {
when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED);
// First set flag to not allow
when(mResources.getBoolean(
R.bool.config_wifiAllowInsecureEnterpriseConfigurationsForSettingsAndSUW))
.thenReturn(false);
when(mWifiConfigManager.addOrUpdateNetwork(any(), anyInt(), any())).thenReturn(
new NetworkUpdateResult(0));
// Create an insecure Enterprise network
WifiConfiguration config = WifiConfigurationTestUtil.createEapNetwork();
config.enterpriseConfig.setCaPath(null);
config.enterpriseConfig.setDomainSuffixMatch(null);
// Verify operation fails
mLooper.startAutoDispatch();
assertEquals(-1, mWifiServiceImpl.addOrUpdateNetwork(config, TEST_PACKAGE_NAME));
mLooper.stopAutoDispatchAndIgnoreExceptions();
verify(mWifiConfigManager, never()).addOrUpdateNetwork(any(), anyInt(), any());
// Set flag to allow
when(mResources.getBoolean(
R.bool.config_wifiAllowInsecureEnterpriseConfigurationsForSettingsAndSUW))
.thenReturn(true);
// Verify operation succeeds
mLooper.startAutoDispatch();
assertEquals(0, WifiConfigurationUtil.removeSecurityTypeFromNetworkId(
mWifiServiceImpl.addOrUpdateNetwork(config, TEST_PACKAGE_NAME)));
mLooper.stopAutoDispatchAndIgnoreExceptions();
verify(mWifiConfigManager).addOrUpdateNetwork(any(), anyInt(), any());
}
/**
* Verify that if the caller does NOT have NETWORK_SETTINGS permission, then it cannot add an
* insecure Enterprise network, with Root CA certificate not set and/or domain name not set,
* regardless of the overlay config_wifiAllowInsecureEnterpriseConfigurationsForSettingsAndSUW
* value.
*/
@Test
public void testAddInsecureEnterpirseNetworkWithNoNetworkSettingsPerm() throws Exception {
// First set flag to not allow
when(mResources.getBoolean(
R.bool.config_wifiAllowInsecureEnterpriseConfigurationsForSettingsAndSUW))
.thenReturn(false);
// Create an insecure Enterprise network
WifiConfiguration config = WifiConfigurationTestUtil.createEapNetwork();
config.enterpriseConfig.setCaPath(null);
config.enterpriseConfig.setDomainSuffixMatch(null);
// Verify operation fails
mLooper.startAutoDispatch();
assertEquals(-1, mWifiServiceImpl.addOrUpdateNetwork(config, TEST_PACKAGE_NAME));
mLooper.stopAutoDispatchAndIgnoreExceptions();
verify(mWifiConfigManager, never()).addOrUpdateNetwork(any(), anyInt(), any());
// Set flag to allow
when(mResources.getBoolean(
R.bool.config_wifiAllowInsecureEnterpriseConfigurationsForSettingsAndSUW))
.thenReturn(true);
// Verify operation still fails
mLooper.startAutoDispatch();
assertEquals(-1, mWifiServiceImpl.addOrUpdateNetwork(config, TEST_PACKAGE_NAME));
mLooper.stopAutoDispatchAndIgnoreExceptions();
verify(mWifiConfigManager, never()).addOrUpdateNetwork(any(), anyInt(), any());
}
private List<WifiConfiguration> setupMultiTypeConfigs(
long featureFlags, boolean saeAutoUpgradeEnabled, boolean oweAutoUpgradeEnabled) {
when(mClientModeManager.getSupportedFeatures()).thenReturn(featureFlags);
when(mWifiGlobals.isWpa3SaeUpgradeEnabled()).thenReturn(saeAutoUpgradeEnabled);
when(mWifiGlobals.isOweUpgradeEnabled()).thenReturn(oweAutoUpgradeEnabled);
List<WifiConfiguration> multiTypeConfigs = new ArrayList<>();
multiTypeConfigs.add(WifiConfigurationTestUtil.createOpenOweNetwork());
multiTypeConfigs.add(WifiConfigurationTestUtil.createPskSaeNetwork());
multiTypeConfigs.add(WifiConfigurationTestUtil.createWpa2Wpa3EnterpriseNetwork());
// Add a valid network ID for each multi-type config to verify the network IDs of the
// single-type configs.
int i = 0;
for (WifiConfiguration config : multiTypeConfigs) {
config.networkId = i++;
}
return multiTypeConfigs;
}
private boolean isSecurityParamsSupported(SecurityParams params, long wifiFeatures) {
switch (params.getSecurityType()) {
case WifiConfiguration.SECURITY_TYPE_SAE:
return 0 != (wifiFeatures & WifiManager.WIFI_FEATURE_WPA3_SAE);
case WifiConfiguration.SECURITY_TYPE_OWE:
return 0 != (wifiFeatures & WifiManager.WIFI_FEATURE_OWE);
}
return true;
}
private List<WifiConfiguration> generateExpectedConfigs(
List<WifiConfiguration> testConfigs,
boolean saeAutoUpgradeEnabled, boolean oweAutoUpgradeEnabled) {
WifiConfiguration tmpConfig;
List<WifiConfiguration> expectedConfigs = new ArrayList<>();
tmpConfig = new WifiConfiguration(testConfigs.get(0));
tmpConfig.setSecurityParams(
SecurityParams.createSecurityParamsBySecurityType(
WifiConfiguration.SECURITY_TYPE_OPEN));
expectedConfigs.add(tmpConfig);
if (oweAutoUpgradeEnabled) {
tmpConfig = new WifiConfiguration(testConfigs.get(0));
tmpConfig.setSecurityParams(
SecurityParams.createSecurityParamsBySecurityType(
WifiConfiguration.SECURITY_TYPE_OWE));
expectedConfigs.add(tmpConfig);
}
tmpConfig = new WifiConfiguration(testConfigs.get(1));
tmpConfig.setSecurityParams(
SecurityParams.createSecurityParamsBySecurityType(
WifiConfiguration.SECURITY_TYPE_PSK));
expectedConfigs.add(tmpConfig);
if (saeAutoUpgradeEnabled) {
tmpConfig = new WifiConfiguration(testConfigs.get(1));
tmpConfig.setSecurityParams(
SecurityParams.createSecurityParamsBySecurityType(
WifiConfiguration.SECURITY_TYPE_SAE));
expectedConfigs.add(tmpConfig);
}
tmpConfig = new WifiConfiguration(testConfigs.get(2));
tmpConfig.setSecurityParams(
SecurityParams.createSecurityParamsBySecurityType(
WifiConfiguration.SECURITY_TYPE_EAP));
expectedConfigs.add(tmpConfig);
if (SdkLevel.isAtLeastS()) {
// WPA2/WPA3-Enterprise config maps only to WPA2-Enterprise for R, but should map to
// both WPA2 and WPA3-Enterprise for S and beyond.
tmpConfig = new WifiConfiguration(testConfigs.get(2));
tmpConfig.setSecurityParams(
SecurityParams.createSecurityParamsBySecurityType(
WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE));
expectedConfigs.add(tmpConfig);
} else {
for (WifiConfiguration config : expectedConfigs) {
config.networkId = WifiConfigurationUtil.addSecurityTypeToNetworkId(
config.networkId, config.getDefaultSecurityParams().getSecurityType());
}
}
return expectedConfigs;
}
/**
* verify multi-type configs are converted to legacy configs in getConfiguredNetworks
* and getPrivilegedConfiguredNetworks when auto-upgrade is enabled.
*/
@Test
public void testGetConfiguredNetworksForMultiTypeConfigs() {
long featureFlags = WifiManager.WIFI_FEATURE_WPA3_SAE | WifiManager.WIFI_FEATURE_OWE;
List<WifiConfiguration> testConfigs = setupMultiTypeConfigs(
featureFlags, true, true);
when(mWifiConfigManager.getSavedNetworks(anyInt()))
.thenReturn(testConfigs);
when(mWifiConfigManager.getConfiguredNetworksWithPasswords())
.thenReturn(testConfigs);
when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED);
mLooper.startAutoDispatch();
ParceledListSlice<WifiConfiguration> configs =
mWifiServiceImpl.getConfiguredNetworks(TEST_PACKAGE, TEST_FEATURE_ID, false);
ParceledListSlice<WifiConfiguration> privilegedConfigs =
mWifiServiceImpl.getPrivilegedConfiguredNetworks(TEST_PACKAGE, TEST_FEATURE_ID);
mLooper.stopAutoDispatchAndIgnoreExceptions();
List<WifiConfiguration> expectedConfigs = generateExpectedConfigs(
testConfigs, true, true);
WifiConfigurationTestUtil.assertConfigurationsEqual(
expectedConfigs, configs.getList());
WifiConfigurationTestUtil.assertConfigurationsEqual(
expectedConfigs, privilegedConfigs.getList());
}
/**
* verify multi-type configs are converted to legacy configs in getConfiguredNetworks
* and getPrivilegedConfiguredNetworks when auto-upgrade is not enabled.
*/
@Test
public void testGetConfiguredNetworksForMultiTypeConfigsWithoutAutoUpgradeEnabled() {
long featureFlags = WifiManager.WIFI_FEATURE_WPA3_SAE | WifiManager.WIFI_FEATURE_OWE;
List<WifiConfiguration> testConfigs = setupMultiTypeConfigs(
featureFlags, false, false);
when(mWifiConfigManager.getSavedNetworks(anyInt()))
.thenReturn(testConfigs);
when(mWifiConfigManager.getConfiguredNetworksWithPasswords())
.thenReturn(testConfigs);
when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED);
mLooper.startAutoDispatch();
ParceledListSlice<WifiConfiguration> configs =
mWifiServiceImpl.getConfiguredNetworks(TEST_PACKAGE, TEST_FEATURE_ID, false);
ParceledListSlice<WifiConfiguration> privilegedConfigs =
mWifiServiceImpl.getPrivilegedConfiguredNetworks(TEST_PACKAGE, TEST_FEATURE_ID);
mLooper.stopAutoDispatchAndIgnoreExceptions();
List<WifiConfiguration> expectedConfigs = generateExpectedConfigs(
testConfigs, false, false);
WifiConfigurationTestUtil.assertConfigurationsEqual(
expectedConfigs, configs.getList());
WifiConfigurationTestUtil.assertConfigurationsEqual(
expectedConfigs, privilegedConfigs.getList());
}
/**
* verify multi-type configs are converted to legacy configs in getConfiguredNetworks
* and getPrivilegedConfiguredNetworks when security types are not supported.
*/
@Test
public void testGetConfiguredNetworksForMultiTypeConfigsWithoutHwSupport() {
long featureFlags = 0L;
List<WifiConfiguration> testConfigs = setupMultiTypeConfigs(
featureFlags, true, true);
when(mWifiConfigManager.getSavedNetworks(anyInt()))
.thenReturn(testConfigs);
when(mWifiConfigManager.getConfiguredNetworksWithPasswords())
.thenReturn(testConfigs);
when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED);
mLooper.startAutoDispatch();
ParceledListSlice<WifiConfiguration> configs =
mWifiServiceImpl.getConfiguredNetworks(TEST_PACKAGE, TEST_FEATURE_ID, false);
ParceledListSlice<WifiConfiguration> privilegedConfigs =
mWifiServiceImpl.getPrivilegedConfiguredNetworks(TEST_PACKAGE, TEST_FEATURE_ID);
mLooper.stopAutoDispatchAndIgnoreExceptions();
List<WifiConfiguration> expectedConfigs = generateExpectedConfigs(
testConfigs, true, true);
WifiConfigurationTestUtil.assertConfigurationsEqual(
expectedConfigs, configs.getList());
WifiConfigurationTestUtil.assertConfigurationsEqual(
expectedConfigs, privilegedConfigs.getList());
}
}