diff options
5 files changed, 107 insertions, 9 deletions
diff --git a/libwifi_system/hostapd_manager.cpp b/libwifi_system/hostapd_manager.cpp index 68184e901..658eecdd8 100644 --- a/libwifi_system/hostapd_manager.cpp +++ b/libwifi_system/hostapd_manager.cpp @@ -34,6 +34,7 @@ using android::base::ParseInt; using android::base::ReadFileToString; +using android::base::RemoveFileIfExists; using android::base::StringPrintf; using android::base::WriteStringToFile; using std::string; @@ -103,6 +104,9 @@ bool HostapdManager::StopHostapd() { } bool HostapdManager::WriteHostapdConfig(const string& config) { + // Remove hostapd.conf because its file owner might be system + // in previous OS and chmod fails in that case. + RemoveFileIfExists(kHostapdConfigFilePath); if (!WriteStringToFile(config, kHostapdConfigFilePath, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, AID_WIFI, AID_WIFI)) { diff --git a/service/java/com/android/server/wifi/WifiConfigManager.java b/service/java/com/android/server/wifi/WifiConfigManager.java index 06b53be85..02f8302f9 100644 --- a/service/java/com/android/server/wifi/WifiConfigManager.java +++ b/service/java/com/android/server/wifi/WifiConfigManager.java @@ -2572,10 +2572,12 @@ public class WifiConfigManager { * @param userId The identifier of the user that stopped. */ public void handleUserStop(int userId) { + if (mVerboseLoggingEnabled) { + Log.v(TAG, "Handling user stop for " + userId); + } if (userId == mCurrentUserId && mUserManager.isUserUnlockingOrUnlocked(mCurrentUserId)) { saveToStore(true); - clearInternalData(); - mCurrentUserId = UserHandle.USER_SYSTEM; + clearInternalUserData(mCurrentUserId); } } @@ -2587,6 +2589,7 @@ public class WifiConfigManager { * - List of deleted ephemeral networks. */ private void clearInternalData() { + localLog("clearInternalData: Clearing all internal data"); mConfiguredNetworks.clear(); mDeletedEphemeralSSIDs.clear(); mScanDetailCaches.clear(); @@ -2605,12 +2608,16 @@ public class WifiConfigManager { * removed from memory. */ private Set<Integer> clearInternalUserData(int userId) { + localLog("clearInternalUserData: Clearing user internal data for " + userId); Set<Integer> removedNetworkIds = new HashSet<>(); // Remove any private networks of the old user before switching the userId. for (WifiConfiguration config : getInternalConfiguredNetworks()) { if (!config.shared && WifiConfigurationUtil.doesUidBelongToAnyProfile( config.creatorUid, mUserManager.getProfiles(userId))) { removedNetworkIds.add(config.networkId); + localLog("clearInternalUserData: removed config." + + " netId=" + config.networkId + + " configKey=" + config.configKey()); mConfiguredNetworks.remove(config.networkId); } } diff --git a/service/java/com/android/server/wifi/scanner/WificondScannerImpl.java b/service/java/com/android/server/wifi/scanner/WificondScannerImpl.java index 12a0bdee0..ed25e0f67 100644 --- a/service/java/com/android/server/wifi/scanner/WificondScannerImpl.java +++ b/service/java/com/android/server/wifi/scanner/WificondScannerImpl.java @@ -422,11 +422,22 @@ public class WificondScannerImpl extends WifiScannerImpl implements Handler.Call mPendingSingleScanEventHandler = null; } - if ((newScanSettings.backgroundScanActive || newScanSettings.singleScanActive) - && !allFreqs.isEmpty()) { - pauseHwPnoScan(); - Set<Integer> freqs = allFreqs.getScanFreqs(); - boolean success = mWifiNative.scan(freqs, hiddenNetworkSSIDSet); + if (newScanSettings.backgroundScanActive || newScanSettings.singleScanActive) { + boolean success = false; + Set<Integer> freqs; + if (!allFreqs.isEmpty()) { + pauseHwPnoScan(); + freqs = allFreqs.getScanFreqs(); + success = mWifiNative.scan(freqs, hiddenNetworkSSIDSet); + if (!success) { + Log.e(TAG, "Failed to start scan, freqs=" + freqs); + } + } else { + // There is a scan request but no available channels could be scanned for. + // We regard it as a scan failure in this case. + Log.e(TAG, "Failed to start scan because there is " + + "no available channel to scan for"); + } if (success) { // TODO handle scan timeout if (DBG) { @@ -439,7 +450,6 @@ public class WificondScannerImpl extends WifiScannerImpl implements Handler.Call mClock.getElapsedSinceBootMillis() + SCAN_TIMEOUT_MS, TIMEOUT_ALARM_TAG, mScanTimeoutListener, mEventHandler); } else { - Log.e(TAG, "Failed to start scan, freqs=" + freqs); // indicate scan failure async mEventHandler.post(new Runnable() { public void run() { diff --git a/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java b/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java index 7ce53629b..0fa660081 100644 --- a/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java +++ b/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java @@ -2406,7 +2406,7 @@ public class WifiConfigManagerTest { } /** - * Verifies that the foreground user stop using {@link WifiConfigManager#handleUserStop(int)} + * Verifies that the user stop handling using {@link WifiConfigManager#handleUserStop(int)} * and ensures that the store is written only when the foreground user is stopped. */ @Test @@ -2429,6 +2429,49 @@ public class WifiConfigManagerTest { } /** + * Verifies that the user stop handling using {@link WifiConfigManager#handleUserStop(int)} + * and ensures that the shared data is not lost when the foreground user is stopped. + */ + @Test + public void testHandleUserStopDoesNotClearSharedData() throws Exception { + int user1 = TEST_DEFAULT_USER; + + // + // Setup the database for the user before initiating stop. + // + int appId = 674; + // Create 2 networks. 1 for user1, and 1 shared. + final WifiConfiguration user1Network = WifiConfigurationTestUtil.createPskNetwork(); + user1Network.shared = false; + user1Network.creatorUid = UserHandle.getUid(user1, appId); + final WifiConfiguration sharedNetwork = WifiConfigurationTestUtil.createPskNetwork(); + + // Set up the store data that is loaded initially. + List<WifiConfiguration> sharedNetworks = new ArrayList<WifiConfiguration>() { + { + add(sharedNetwork); + } + }; + List<WifiConfiguration> user1Networks = new ArrayList<WifiConfiguration>() { + { + add(user1Network); + } + }; + setupStoreDataForRead(sharedNetworks, user1Networks, new HashSet<String>()); + assertTrue(mWifiConfigManager.loadFromStore()); + verify(mWifiConfigStore).read(); + + // Ensure that we have 2 networks in the database before the stop. + assertEquals(2, mWifiConfigManager.getConfiguredNetworks().size()); + + mWifiConfigManager.handleUserStop(user1); + + // Ensure that we only have 1 shared network in the database after the stop. + assertEquals(1, mWifiConfigManager.getConfiguredNetworks().size()); + assertEquals(sharedNetwork.SSID, mWifiConfigManager.getConfiguredNetworks().get(0).SSID); + } + + /** * Verifies the foreground user unlock via {@link WifiConfigManager#handleUserUnlock(int)} * results in a store read after bootup. */ diff --git a/tests/wifitests/src/com/android/server/wifi/scanner/WificondScannerTest.java b/tests/wifitests/src/com/android/server/wifi/scanner/WificondScannerTest.java index ed7c58298..d337cf1cf 100644 --- a/tests/wifitests/src/com/android/server/wifi/scanner/WificondScannerTest.java +++ b/tests/wifitests/src/com/android/server/wifi/scanner/WificondScannerTest.java @@ -32,6 +32,7 @@ import com.android.server.wifi.ScanDetail; import com.android.server.wifi.ScanResults; import com.android.server.wifi.WifiMonitor; import com.android.server.wifi.WifiNative; +import com.android.server.wifi.scanner.ChannelHelper.ChannelCollection; import org.junit.Before; import org.junit.Test; @@ -56,6 +57,39 @@ public class WificondScannerTest extends BaseWifiScannerImplTest { mLooper.getLooper(), mClock); } + /** + * Test that WificondScannerImpl will not issue a scan and report scan failure + * when there is no channel to scan for. + */ + @Test + public void singleScanNotIssuedIfNoAvailableChannels() { + // Use mocked ChannelHelper and ChannelCollection to simulate the scenario + // that no channel is available for this request. + ChannelHelper channelHelper = mock(ChannelHelper.class); + ChannelCollection channelCollection = mock(ChannelCollection.class); + when(channelHelper.createChannelCollection()).thenReturn(channelCollection); + when(channelCollection.isEmpty()).thenReturn(true); + + mScanner = new WificondScannerImpl(mContext, mWifiNative, mWifiMonitor, + channelHelper, mLooper.getLooper(), mClock); + + WifiNative.ScanSettings settings = new NativeScanSettingsBuilder() + .withBasePeriod(10000) // ms + .withMaxApPerScan(10) + .addBucketWithBand(10000 /* ms */, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN, + WifiScanner.WIFI_BAND_5_GHZ) + .build(); + WifiNative.ScanEventHandler eventHandler = mock(WifiNative.ScanEventHandler.class); + mScanner.startSingleScan(settings, eventHandler); + + mLooper.dispatchAll(); + + // No scan is issued to WifiNative. + verify(mWifiNative, never()).scan(any(), any(Set.class)); + // A scan failed event must be reported. + verify(eventHandler).onScanStatus(WifiNative.WIFI_SCAN_FAILED); + } + @Test public void backgroundScanSuccessSingleBucket() { WifiNative.ScanSettings settings = new NativeScanSettingsBuilder() |