diff options
author | android-build-team Robot <android-build-team-robot@google.com> | 2017-06-11 07:11:59 +0000 |
---|---|---|
committer | android-build-team Robot <android-build-team-robot@google.com> | 2017-06-11 07:11:59 +0000 |
commit | 14b418103501f5106632a7af95b067aee7c7b026 (patch) | |
tree | fe011daac6ada61fe8226b7a53a0ed716f5dba3b | |
parent | 79ad93863288ad115be97db7e85468201183eb5f (diff) | |
parent | 8ec0ba59c20b8266d735912fb71575834c991acc (diff) | |
download | android_frameworks_opt_net_wifi-14b418103501f5106632a7af95b067aee7c7b026.tar.gz android_frameworks_opt_net_wifi-14b418103501f5106632a7af95b067aee7c7b026.tar.bz2 android_frameworks_opt_net_wifi-14b418103501f5106632a7af95b067aee7c7b026.zip |
release-request-276f9f52-87fd-4915-bd79-9a2f0ee77433-for-git_oc-release-4090213 snap-temp-L31600000073091223
Change-Id: If0e4eed6ea22ca45ef260d8de6301f8876fba841
12 files changed, 200 insertions, 98 deletions
diff --git a/service/java/com/android/server/wifi/FrameworkFacade.java b/service/java/com/android/server/wifi/FrameworkFacade.java index 2c3e5f7e0..ba114df8a 100644 --- a/service/java/com/android/server/wifi/FrameworkFacade.java +++ b/service/java/com/android/server/wifi/FrameworkFacade.java @@ -16,6 +16,7 @@ package com.android.server.wifi; +import android.app.ActivityManager; import android.app.AppGlobals; import android.app.PendingIntent; import android.content.Context; @@ -161,4 +162,14 @@ public class FrameworkFacade { public boolean inStorageManagerCryptKeeperBounce() { return StorageManager.inCryptKeeperBounce(); } + + /** + * Check if the provided uid is the app in the foreground. + * @param uid the uid to check + * @return true if the app is in the foreground, false otherwise + * @throws RemoteException + */ + public boolean isAppForeground(int uid) throws RemoteException { + return ActivityManager.getService().isAppForeground(uid); + } } diff --git a/service/java/com/android/server/wifi/WifiBackupRestore.java b/service/java/com/android/server/wifi/WifiBackupRestore.java index 4095d8283..60c3b488d 100644 --- a/service/java/com/android/server/wifi/WifiBackupRestore.java +++ b/service/java/com/android/server/wifi/WifiBackupRestore.java @@ -28,6 +28,7 @@ import android.util.Xml; import com.android.internal.util.FastXmlSerializer; import com.android.server.net.IpConfigStore; import com.android.server.wifi.util.NativeUtil; +import com.android.server.wifi.util.WifiPermissionsUtil; import com.android.server.wifi.util.XmlUtil; import com.android.server.wifi.util.XmlUtil.IpConfigurationXmlUtil; import com.android.server.wifi.util.XmlUtil.WifiConfigurationXmlUtil; @@ -96,6 +97,7 @@ public class WifiBackupRestore { private static final String WEP_KEYS_MASK_SEARCH_PATTERN = "(<.*=)(.*)(/>)"; private static final String WEP_KEYS_MASK_REPLACE_PATTERN = "$1*$3"; + private final WifiPermissionsUtil mWifiPermissionsUtil; /** * Verbose logging flag. */ @@ -109,6 +111,10 @@ public class WifiBackupRestore { private byte[] mDebugLastBackupDataRestored; private byte[] mDebugLastSupplicantBackupDataRestored; + public WifiBackupRestore(WifiPermissionsUtil wifiPermissionsUtil) { + mWifiPermissionsUtil = wifiPermissionsUtil; + } + /** * Retrieve an XML byte stream representing the data that needs to be backed up from the * provided configurations. @@ -163,7 +169,9 @@ public class WifiBackupRestore { if (configuration.isEnterprise() || configuration.isPasspoint()) { continue; } - if (configuration.creatorUid >= Process.FIRST_APPLICATION_UID) { + if (!mWifiPermissionsUtil.checkConfigOverridePermission(configuration.creatorUid)) { + Log.d(TAG, "Ignoring network from an app with no config override permission: " + + configuration.configKey()); continue; } // Write this configuration data now. @@ -702,6 +710,8 @@ public class WifiBackupRestore { Integer.parseInt(extras.get( SupplicantStaNetworkHal.ID_STRING_KEY_CREATOR_UID)); if (creatorUid >= Process.FIRST_APPLICATION_UID) { + Log.d(TAG, "Ignoring network from non-system app: " + + configuration.configKey()); return null; } } diff --git a/service/java/com/android/server/wifi/WifiInjector.java b/service/java/com/android/server/wifi/WifiInjector.java index 90e400cc1..c51778578 100644 --- a/service/java/com/android/server/wifi/WifiInjector.java +++ b/service/java/com/android/server/wifi/WifiInjector.java @@ -96,7 +96,7 @@ public class WifiInjector { private final PropertyService mPropertyService = new SystemPropertyService(); private final BuildProperties mBuildProperties = new SystemBuildProperties(); private final KeyStore mKeyStore = KeyStore.getInstance(); - private final WifiBackupRestore mWifiBackupRestore = new WifiBackupRestore(); + private final WifiBackupRestore mWifiBackupRestore; private final WifiMulticastLockManager mWifiMulticastLockManager; private final WifiConfigStore mWifiConfigStore; private final WifiKeyStore mWifiKeyStore; @@ -150,6 +150,7 @@ public class WifiInjector { mWifiNetworkScoreCache, NetworkScoreManager.CACHE_FILTER_NONE); mWifiPermissionsUtil = new WifiPermissionsUtil(mWifiPermissionsWrapper, mContext, mSettingsStore, UserManager.get(mContext), mNetworkScoreManager, this); + mWifiBackupRestore = new WifiBackupRestore(mWifiPermissionsUtil); mBatteryStats = IBatteryStats.Stub.asInterface(mFrameworkFacade.getService( BatteryStats.SERVICE_NAME)); mWifiStateTracker = new WifiStateTracker(mBatteryStats); diff --git a/service/java/com/android/server/wifi/WifiMonitor.java b/service/java/com/android/server/wifi/WifiMonitor.java index 385bfccaa..b2fc56e25 100644 --- a/service/java/com/android/server/wifi/WifiMonitor.java +++ b/service/java/com/android/server/wifi/WifiMonitor.java @@ -179,9 +179,9 @@ public class WifiMonitor { if (mConnected) { return true; } - if (connectTries++ < 5) { + if (connectTries++ < 50) { try { - Thread.sleep(1000); + Thread.sleep(100); } catch (InterruptedException ignore) { } } else { diff --git a/service/java/com/android/server/wifi/WifiServiceImpl.java b/service/java/com/android/server/wifi/WifiServiceImpl.java index d32a579ac..5c9548a54 100644 --- a/service/java/com/android/server/wifi/WifiServiceImpl.java +++ b/service/java/com/android/server/wifi/WifiServiceImpl.java @@ -1159,6 +1159,16 @@ public class WifiServiceImpl extends IWifiManager.Stub { return LocalOnlyHotspotCallback.ERROR_TETHERING_DISALLOWED; } + // the app should be in the foreground + try { + if (!mFrameworkFacade.isAppForeground(uid)) { + return LocalOnlyHotspotCallback.ERROR_INCOMPATIBLE_MODE; + } + } catch (RemoteException e) { + mLog.trace("RemoteException during isAppForeground when calling startLOHS"); + return LocalOnlyHotspotCallback.ERROR_INCOMPATIBLE_MODE; + } + mLog.trace("startLocalOnlyHotspot uid=% pid=%").c(uid).c(pid).flush(); synchronized (mLocalOnlyHotspotRequests) { @@ -2511,8 +2521,7 @@ public class WifiServiceImpl extends IWifiManager.Stub { */ @Override public byte[] retrieveBackupData() { - enforceReadCredentialPermission(); - enforceAccessPermission(); + enforceNetworkSettingsPermission(); mLog.trace("retrieveBackupData uid=%").c(Binder.getCallingUid()).flush(); if (mWifiStateMachineChannel == null) { Slog.e(TAG, "mWifiStateMachineChannel is not initialized"); @@ -2557,7 +2566,7 @@ public class WifiServiceImpl extends IWifiManager.Stub { */ @Override public void restoreBackupData(byte[] data) { - enforceChangePermission(); + enforceNetworkSettingsPermission(); mLog.trace("restoreBackupData uid=%").c(Binder.getCallingUid()).flush(); if (mWifiStateMachineChannel == null) { Slog.e(TAG, "mWifiStateMachineChannel is not initialized"); @@ -2579,7 +2588,7 @@ public class WifiServiceImpl extends IWifiManager.Stub { * @param ipConfigData Raw byte stream of ipconfig.txt */ public void restoreSupplicantBackupData(byte[] supplicantData, byte[] ipConfigData) { - enforceChangePermission(); + enforceNetworkSettingsPermission(); mLog.trace("restoreSupplicantBackupData uid=%").c(Binder.getCallingUid()).flush(); if (mWifiStateMachineChannel == null) { Slog.e(TAG, "mWifiStateMachineChannel is not initialized"); diff --git a/service/java/com/android/server/wifi/WifiVendorHal.java b/service/java/com/android/server/wifi/WifiVendorHal.java index 9c1ae94b5..88f189814 100644 --- a/service/java/com/android/server/wifi/WifiVendorHal.java +++ b/service/java/com/android/server/wifi/WifiVendorHal.java @@ -64,6 +64,7 @@ import android.net.wifi.WifiManager; import android.net.wifi.WifiScanner; import android.net.wifi.WifiSsid; import android.net.wifi.WifiWakeReasonAndCounts; +import android.os.Handler; import android.os.Looper; import android.os.RemoteException; import android.util.MutableBoolean; @@ -204,16 +205,23 @@ public class WifiVendorHal { private IWifiRttController mIWifiRttController; private final HalDeviceManager mHalDeviceManager; private final HalDeviceManagerStatusListener mHalDeviceManagerStatusCallbacks; - private final Looper mLooper; private final IWifiStaIfaceEventCallback mIWifiStaIfaceEventCallback; private final IWifiChipEventCallback mIWifiChipEventCallback; private final RttEventCallback mRttEventCallback; + // Plumbing for event handling. + // + // Being final fields, they can be accessed without synchronization under + // some reasonable assumptions. See + // https://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.5 + private final Looper mLooper; + private final Handler mHalEventHandler; public WifiVendorHal(HalDeviceManager halDeviceManager, Looper looper) { mHalDeviceManager = halDeviceManager; mLooper = looper; + mHalEventHandler = new Handler(looper); mHalDeviceManagerStatusCallbacks = new HalDeviceManagerStatusListener(); mIWifiStaIfaceEventCallback = new StaIfaceEventCallback(); mIWifiChipEventCallback = new ChipEventCallback(); @@ -2455,25 +2463,47 @@ public class WifiVendorHal { WifiDebugRingBufferStatus status, java.util.ArrayList<Byte> data) { //TODO(b/35875078) Reinstate logging when execessive callbacks are fixed // mVerboseLog.d("onDebugRingBufferDataAvailable " + status); - WifiNative.WifiLoggerEventHandler eventHandler; - synchronized (sLock) { - if (mLogEventHandler == null || status == null || data == null) return; - eventHandler = mLogEventHandler; - } - eventHandler.onRingBufferData( - ringBufferStatus(status), NativeUtil.byteArrayFromArrayList(data)); + mHalEventHandler.post(() -> { + WifiNative.WifiLoggerEventHandler eventHandler; + synchronized (sLock) { + if (mLogEventHandler == null || status == null || data == null) return; + eventHandler = mLogEventHandler; + } + // Because |sLock| has been released, there is a chance that we'll execute + // a spurious callback (after someone has called resetLogHandler()). + // + // However, the alternative risks deadlock. Consider: + // [T1.1] WifiDiagnostics.captureBugReport() + // [T1.2] -- acquire WifiDiagnostics object's intrinsic lock + // [T1.3] -> WifiVendorHal.getRingBufferData() + // [T1.4] -- acquire WifiVendorHal.sLock + // [T2.1] <lambda>() + // [T2.2] -- acquire WifiVendorHal.sLock + // [T2.3] -> WifiDiagnostics.onRingBufferData() + // [T2.4] -- acquire WifiDiagnostics object's intrinsic lock + // + // The problem here is that the two threads acquire the locks in opposite order. + // If, for example, T2.2 executes between T1.2 and 1.4, then T1 and T2 + // will be deadlocked. + eventHandler.onRingBufferData( + ringBufferStatus(status), NativeUtil.byteArrayFromArrayList(data)); + }); } @Override public void onDebugErrorAlert(int errorCode, java.util.ArrayList<Byte> debugData) { mVerboseLog.d("onDebugErrorAlert " + errorCode); - WifiNative.WifiLoggerEventHandler eventHandler; - synchronized (sLock) { - if (mLogEventHandler == null || debugData == null) return; - eventHandler = mLogEventHandler; - } - eventHandler.onWifiAlert( - errorCode, NativeUtil.byteArrayFromArrayList(debugData)); + mHalEventHandler.post(() -> { + WifiNative.WifiLoggerEventHandler eventHandler; + synchronized (sLock) { + if (mLogEventHandler == null || debugData == null) return; + eventHandler = mLogEventHandler; + } + // See comment in onDebugRingBufferDataAvailable(), for an explanation + // of why this callback is invoked without |sLock| held. + eventHandler.onWifiAlert( + errorCode, NativeUtil.byteArrayFromArrayList(debugData)); + }); } } diff --git a/service/java/com/android/server/wifi/p2p/WifiP2pMonitor.java b/service/java/com/android/server/wifi/p2p/WifiP2pMonitor.java index 0411f3073..e14c10c91 100644 --- a/service/java/com/android/server/wifi/p2p/WifiP2pMonitor.java +++ b/service/java/com/android/server/wifi/p2p/WifiP2pMonitor.java @@ -158,9 +158,9 @@ public class WifiP2pMonitor { if (mConnected) { return true; } - if (connectTries++ < 5) { + if (connectTries++ < 50) { try { - Thread.sleep(1000); + Thread.sleep(100); } catch (InterruptedException ignore) { } } else { diff --git a/service/java/com/android/server/wifi/scanner/WifiScanningServiceImpl.java b/service/java/com/android/server/wifi/scanner/WifiScanningServiceImpl.java index 771e336d5..08c9e1359 100644 --- a/service/java/com/android/server/wifi/scanner/WifiScanningServiceImpl.java +++ b/service/java/com/android/server/wifi/scanner/WifiScanningServiceImpl.java @@ -447,7 +447,6 @@ public class WifiScanningServiceImpl extends IWifiScanner.Stub { private RequestList<ScanSettings> mActiveScans = new RequestList<>(); private RequestList<ScanSettings> mPendingScans = new RequestList<>(); - // Scan results cached from the last full single scan request. private ScanResult[] mCachedScanResults = new ScanResult[0]; WifiSingleScanStateMachine(Looper looper) { @@ -880,11 +879,8 @@ public class WifiScanningServiceImpl extends IWifiScanner.Stub { entry.reportEvent(WifiScanner.CMD_SCAN_RESULT, 0, parcelableAllResults); } - // Since we use NoBandChannelHelper, as long as a specific band is mentioned, the scan - // request is treated as full band (WifiScanner.WIFI_BAND_*). - if (results.isAllChannelsScanned()) { - mCachedScanResults = results.getResults(); - } + // Cache the results here so that apps can retrieve them. + mCachedScanResults = results.getResults(); sendScanResultBroadcast(true); } diff --git a/tests/wifitests/src/com/android/server/wifi/WifiBackupRestoreTest.java b/tests/wifitests/src/com/android/server/wifi/WifiBackupRestoreTest.java index 362540517..58b8d394b 100644 --- a/tests/wifitests/src/com/android/server/wifi/WifiBackupRestoreTest.java +++ b/tests/wifitests/src/com/android/server/wifi/WifiBackupRestoreTest.java @@ -24,10 +24,13 @@ import android.os.Process; import android.test.suitebuilder.annotation.SmallTest; import com.android.server.net.IpConfigStore; +import com.android.server.wifi.util.WifiPermissionsUtil; import org.junit.After; import org.junit.Before; import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; @@ -48,11 +51,15 @@ import java.util.Random; @SmallTest public class WifiBackupRestoreTest { - private final WifiBackupRestore mWifiBackupRestore = new WifiBackupRestore(); + @Mock WifiPermissionsUtil mWifiPermissionsUtil; + private WifiBackupRestore mWifiBackupRestore; private boolean mCheckDump = true; @Before public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); + when(mWifiPermissionsUtil.checkConfigOverridePermission(anyInt())).thenReturn(true); + mWifiBackupRestore = new WifiBackupRestore(mWifiPermissionsUtil); // Enable verbose logging before tests to check the backup data dumps. mWifiBackupRestore.enableVerboseLogging(1); } @@ -361,25 +368,34 @@ public class WifiBackupRestoreTest { */ @Test public void testMultipleNetworksSystemAppBackupRestore() { + int systemAppUid = Process.SYSTEM_UID; + int nonSystemAppUid = Process.FIRST_APPLICATION_UID + 556; + when(mWifiPermissionsUtil.checkConfigOverridePermission(eq(systemAppUid))) + .thenReturn(true); + when(mWifiPermissionsUtil.checkConfigOverridePermission(eq(nonSystemAppUid))) + .thenReturn(false); + List<WifiConfiguration> configurations = new ArrayList<>(); List<WifiConfiguration> expectedConfigurations = new ArrayList<>(); WifiConfiguration wepNetwork = WifiConfigurationTestUtil.createWepNetwork(); + wepNetwork.creatorUid = systemAppUid; configurations.add(wepNetwork); expectedConfigurations.add(wepNetwork); // These should not be in |expectedConfigurations|. WifiConfiguration nonSystemAppWepNetwork = WifiConfigurationTestUtil.createWepNetwork(); - nonSystemAppWepNetwork.creatorUid = Process.FIRST_APPLICATION_UID; + nonSystemAppWepNetwork.creatorUid = nonSystemAppUid; configurations.add(nonSystemAppWepNetwork); WifiConfiguration pskNetwork = WifiConfigurationTestUtil.createPskNetwork(); + pskNetwork.creatorUid = systemAppUid; configurations.add(pskNetwork); expectedConfigurations.add(pskNetwork); // These should not be in |expectedConfigurations|. WifiConfiguration nonSystemAppPskNetwork = WifiConfigurationTestUtil.createPskNetwork(); - nonSystemAppPskNetwork.creatorUid = Process.FIRST_APPLICATION_UID + 1; + nonSystemAppPskNetwork.creatorUid = nonSystemAppUid; configurations.add(nonSystemAppPskNetwork); WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork(); diff --git a/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java b/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java index 562143335..d5bfb2045 100644 --- a/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java +++ b/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java @@ -74,6 +74,7 @@ import android.os.Message; import android.os.Messenger; import android.os.PowerManager; import android.os.Process; +import android.os.RemoteException; import android.os.UserManager; import android.os.WorkSource; import android.os.test.TestLooper; @@ -97,6 +98,7 @@ import org.mockito.Spy; import java.io.FileDescriptor; import java.io.PrintWriter; import java.io.StringWriter; +import java.util.List; /** * Unit tests for {@link WifiServiceImpl}. @@ -760,6 +762,9 @@ public class WifiServiceImplTest { // allow test to proceed without a permission check failure when(mSettingsStore.getLocationModeSetting(mContext)) .thenReturn(LOCATION_MODE_HIGH_ACCURACY); + try { + when(mFrameworkFacade.isAppForeground(anyInt())).thenReturn(true); + } catch (RemoteException e) { } when(mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_TETHERING)) .thenReturn(false); int result = mWifiServiceImpl.startLocalOnlyHotspot(mAppMessenger, mAppBinder, @@ -812,12 +817,43 @@ public class WifiServiceImplTest { } /** + * Only start LocalOnlyHotspot if the caller is the foreground app at the time of the request. + */ + @Test + public void testStartLocalOnlyHotspotFailsIfRequestorNotForegroundApp() throws Exception { + when(mSettingsStore.getLocationModeSetting(mContext)) + .thenReturn(LOCATION_MODE_HIGH_ACCURACY); + + when(mFrameworkFacade.isAppForeground(anyInt())).thenReturn(false); + int result = mWifiServiceImpl.startLocalOnlyHotspot(mAppMessenger, mAppBinder, + TEST_PACKAGE_NAME); + assertEquals(LocalOnlyHotspotCallback.ERROR_INCOMPATIBLE_MODE, result); + } + + /** + * Do not register the LocalOnlyHotspot request if the caller app cannot be verified as the + * foreground app at the time of the request (ie, throws an exception in the check). + */ + @Test + public void testStartLocalOnlyHotspotFailsIfForegroundAppCheckThrowsRemoteException() + throws Exception { + when(mSettingsStore.getLocationModeSetting(mContext)) + .thenReturn(LOCATION_MODE_HIGH_ACCURACY); + + when(mFrameworkFacade.isAppForeground(anyInt())).thenThrow(new RemoteException()); + int result = mWifiServiceImpl.startLocalOnlyHotspot(mAppMessenger, mAppBinder, + TEST_PACKAGE_NAME); + assertEquals(LocalOnlyHotspotCallback.ERROR_INCOMPATIBLE_MODE, result); + } + + /** * Only start LocalOnlyHotspot if we are not tethering. */ @Test - public void testHotspotDoesNotStartWhenAlreadyTethering() { + public void testHotspotDoesNotStartWhenAlreadyTethering() throws Exception { when(mSettingsStore.getLocationModeSetting(mContext)) .thenReturn(LOCATION_MODE_HIGH_ACCURACY); + when(mFrameworkFacade.isAppForeground(anyInt())).thenReturn(true); mWifiServiceImpl.updateInterfaceIpState(WIFI_IFACE_NAME, IFACE_IP_MODE_TETHERED); mLooper.dispatchAll(); int returnCode = mWifiServiceImpl.startLocalOnlyHotspot( @@ -829,9 +865,10 @@ public class WifiServiceImplTest { * Only start LocalOnlyHotspot if admin setting does not disallow tethering. */ @Test - public void testHotspotDoesNotStartWhenTetheringDisallowed() { + public void testHotspotDoesNotStartWhenTetheringDisallowed() throws Exception { when(mSettingsStore.getLocationModeSetting(mContext)) .thenReturn(LOCATION_MODE_HIGH_ACCURACY); + when(mFrameworkFacade.isAppForeground(anyInt())).thenReturn(true); when(mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_TETHERING)) .thenReturn(true); int returnCode = mWifiServiceImpl.startLocalOnlyHotspot( @@ -1503,4 +1540,44 @@ public class WifiServiceImplTest { verify(mWifiStateMachine).syncAddOrUpdatePasspointConfig(any(), any(PasspointConfiguration.class), anyInt()); } + + /** + * 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)); + } } diff --git a/tests/wifitests/src/com/android/server/wifi/WifiVendorHalTest.java b/tests/wifitests/src/com/android/server/wifi/WifiVendorHalTest.java index 66a55b51a..34ddf2378 100644 --- a/tests/wifitests/src/com/android/server/wifi/WifiVendorHalTest.java +++ b/tests/wifitests/src/com/android/server/wifi/WifiVendorHalTest.java @@ -1679,9 +1679,10 @@ public class WifiVendorHalTest { new Random().nextBytes(errorData); // Randomly raise the HIDL callback before we register for the log callback. - // This should be ignored. + // This should be safely ignored. (Not trigger NPE.) mIWifiChipEventCallback.onDebugErrorAlert( errorCode, NativeUtil.byteArrayToArrayList(errorData)); + mLooper.dispatchAll(); WifiNative.WifiLoggerEventHandler eventHandler = mock(WifiNative.WifiLoggerEventHandler.class); @@ -1691,12 +1692,16 @@ public class WifiVendorHalTest { // Now raise the HIDL callback, this should be properly handled. mIWifiChipEventCallback.onDebugErrorAlert( errorCode, NativeUtil.byteArrayToArrayList(errorData)); + mLooper.dispatchAll(); verify(eventHandler).onWifiAlert(eq(errorCode), eq(errorData)); // Now stop the logging and invoke the callback. This should be ignored. + reset(eventHandler); assertTrue(mWifiVendorHal.resetLogHandler()); mIWifiChipEventCallback.onDebugErrorAlert( errorCode, NativeUtil.byteArrayToArrayList(errorData)); + mLooper.dispatchAll(); + verify(eventHandler, never()).onWifiAlert(anyInt(), anyObject()); } /** @@ -1714,9 +1719,10 @@ public class WifiVendorHalTest { new Random().nextBytes(errorData); // Randomly raise the HIDL callback before we register for the log callback. - // This should be ignored. + // This should be safely ignored. (Not trigger NPE.) mIWifiChipEventCallback.onDebugRingBufferDataAvailable( new WifiDebugRingBufferStatus(), NativeUtil.byteArrayToArrayList(errorData)); + mLooper.dispatchAll(); WifiNative.WifiLoggerEventHandler eventHandler = mock(WifiNative.WifiLoggerEventHandler.class); @@ -1726,13 +1732,17 @@ public class WifiVendorHalTest { // Now raise the HIDL callback, this should be properly handled. mIWifiChipEventCallback.onDebugRingBufferDataAvailable( new WifiDebugRingBufferStatus(), NativeUtil.byteArrayToArrayList(errorData)); + mLooper.dispatchAll(); verify(eventHandler).onRingBufferData( any(WifiNative.RingBufferStatus.class), eq(errorData)); // Now stop the logging and invoke the callback. This should be ignored. + reset(eventHandler); assertTrue(mWifiVendorHal.resetLogHandler()); mIWifiChipEventCallback.onDebugRingBufferDataAvailable( new WifiDebugRingBufferStatus(), NativeUtil.byteArrayToArrayList(errorData)); + mLooper.dispatchAll(); + verify(eventHandler, never()).onRingBufferData(anyObject(), anyObject()); } /** diff --git a/tests/wifitests/src/com/android/server/wifi/scanner/WifiScanningServiceTest.java b/tests/wifitests/src/com/android/server/wifi/scanner/WifiScanningServiceTest.java index d9fbb1d28..e7c5fa962 100644 --- a/tests/wifitests/src/com/android/server/wifi/scanner/WifiScanningServiceTest.java +++ b/tests/wifitests/src/com/android/server/wifi/scanner/WifiScanningServiceTest.java @@ -1257,10 +1257,10 @@ public class WifiScanningServiceTest { } /** - * Verify that the newest full scan results are returned by WifiService.getSingleScanResults. + * Verify that the newest scan results are returned by WifiService.getSingleScanResults. */ @Test - public void retrieveMostRecentFullSingleScanResults() throws Exception { + public void retrieveMostRecentSingleScanResults() throws Exception { WifiScanner.ScanSettings requestSettings = createRequest(WifiScanner.WIFI_BAND_BOTH, 0, 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN); ScanResults expectedResults = ScanResults.create(0, true, 2400, 5150, 5175); @@ -1312,64 +1312,6 @@ public class WifiScanningServiceTest { } /** - * Verify that the newest partial scan results are not returned by - * WifiService.getSingleScanResults. - */ - @Test - public void doesNotRetrieveMostRecentPartialSingleScanResults() throws Exception { - WifiScanner.ScanSettings fullRequestSettings = createRequest(WifiScanner.WIFI_BAND_BOTH, 0, - 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN); - ScanResults expectedFullResults = ScanResults.create(0, true, 2400, 5150, 5175); - doSuccessfulSingleScan(fullRequestSettings, - computeSingleScanNativeSettings(fullRequestSettings), - expectedFullResults); - - Handler handler = mock(Handler.class); - BidirectionalAsyncChannel controlChannel = connectChannel(handler); - InOrder order = inOrder(handler, mWifiScannerImpl); - - controlChannel.sendMessage( - Message.obtain(null, WifiScanner.CMD_GET_SINGLE_SCAN_RESULTS, 0)); - mLooper.dispatchAll(); - Message response = verifyHandleMessageAndGetMessage(order, handler); - - List<ScanResult> results = Arrays.asList( - ((WifiScanner.ParcelableScanResults) response.obj).getResults()); - assertEquals(results.size(), expectedFullResults.getRawScanResults().length); - - // now update with a new scan that only has one result - int secondScanRequestId = 35; - WifiScanner.ScanSettings partialRequestSettings = createRequest(WifiScanner.WIFI_BAND_BOTH, - 0, 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN); - ScanResults expectedPartialResults = ScanResults.create(0, false, 5150); - sendSingleScanRequest(controlChannel, secondScanRequestId, partialRequestSettings, null); - - mLooper.dispatchAll(); - WifiNative.ScanEventHandler eventHandler = verifyStartSingleScan(order, - computeSingleScanNativeSettings(partialRequestSettings)); - verifySuccessfulResponse(order, handler, secondScanRequestId); - - // dispatch scan 2 results - when(mWifiScannerImpl.getLatestSingleScanResults()) - .thenReturn(expectedPartialResults.getScanData()); - eventHandler.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE); - - mLooper.dispatchAll(); - verifyScanResultsReceived(order, handler, secondScanRequestId, - expectedPartialResults.getScanData()); - verifySingleScanCompletedReceived(order, handler, secondScanRequestId); - - controlChannel.sendMessage( - Message.obtain(null, WifiScanner.CMD_GET_SINGLE_SCAN_RESULTS, 0)); - mLooper.dispatchAll(); - Message response2 = verifyHandleMessageAndGetMessage(order, handler); - - List<ScanResult> results2 = Arrays.asList( - ((WifiScanner.ParcelableScanResults) response2.obj).getResults()); - assertEquals(results2.size(), expectedFullResults.getRawScanResults().length); - } - - /** * Cached scan results should be cleared after the driver is unloaded. */ @Test |