summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--service/java/com/android/server/wifi/FrameworkFacade.java14
-rw-r--r--service/java/com/android/server/wifi/WifiInjector.java10
-rw-r--r--service/java/com/android/server/wifi/WifiScanAlwaysAvailableSettingsCompatibility.java101
-rw-r--r--service/java/com/android/server/wifi/WifiServiceImpl.java3
-rw-r--r--tests/wifitests/src/com/android/server/wifi/WifiScanAlwaysAvailableSettingsCompatibilityTest.java135
-rw-r--r--tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java3
-rw-r--r--tests/wifitests/src/com/android/server/wifi/util/WifiPermissionsUtilTest.java6
7 files changed, 269 insertions, 3 deletions
diff --git a/service/java/com/android/server/wifi/FrameworkFacade.java b/service/java/com/android/server/wifi/FrameworkFacade.java
index d244c3739..20c27d70b 100644
--- a/service/java/com/android/server/wifi/FrameworkFacade.java
+++ b/service/java/com/android/server/wifi/FrameworkFacade.java
@@ -69,6 +69,20 @@ public class FrameworkFacade {
return mActivityManager;
}
+ /**
+ * Mockable setter for Settings.Global
+ */
+ public boolean setIntegerSetting(ContentResolver contentResolver, String name, int value) {
+ return Settings.Global.putInt(contentResolver, name, value);
+ }
+
+ /**
+ * Mockable getter for Settings.Global
+ */
+ public int getIntegerSetting(ContentResolver contentResolver, String name, int def) {
+ return Settings.Global.getInt(contentResolver, name, def);
+ }
+
public boolean setIntegerSetting(Context context, String name, int def) {
return Settings.Global.putInt(getContentResolver(context), name, def);
}
diff --git a/service/java/com/android/server/wifi/WifiInjector.java b/service/java/com/android/server/wifi/WifiInjector.java
index 71f8b7073..158d84058 100644
--- a/service/java/com/android/server/wifi/WifiInjector.java
+++ b/service/java/com/android/server/wifi/WifiInjector.java
@@ -159,6 +159,8 @@ public class WifiInjector {
private final WifiHealthMonitor mWifiHealthMonitor;
private final WifiOemConfigStoreMigrationDataHolder mOemConfigStoreMigrationDataHolder;
private final WifiSettingsConfigStore mSettingsConfigStore;
+ private final WifiScanAlwaysAvailableSettingsCompatibility
+ mWifiScanAlwaysAvailableSettingsCompatibility;
public WifiInjector(Context context) {
if (context == null) {
@@ -339,6 +341,9 @@ public class WifiInjector {
mActiveModeWarden = new ActiveModeWarden(this, wifiLooper,
mWifiNative, new DefaultModeManager(mContext), mBatteryStats, mWifiDiagnostics,
mContext, mClientModeImpl, mSettingsStore, mFrameworkFacade, mWifiPermissionsUtil);
+ mWifiScanAlwaysAvailableSettingsCompatibility =
+ new WifiScanAlwaysAvailableSettingsCompatibility(mContext, wifiHandler,
+ mSettingsStore, mActiveModeWarden, mFrameworkFacade);
mWifiApConfigStore = new WifiApConfigStore(
mContext, this, wifiHandler, mBackupManagerProxy,
mWifiConfigStore, mWifiConfigManager, mActiveModeWarden);
@@ -820,4 +825,9 @@ public class WifiInjector {
public WifiSettingsConfigStore getSettingsConfigStore() {
return mSettingsConfigStore;
}
+
+ public WifiScanAlwaysAvailableSettingsCompatibility
+ getWifiScanAlwaysAvailableSettingsCompatibility() {
+ return mWifiScanAlwaysAvailableSettingsCompatibility;
+ }
}
diff --git a/service/java/com/android/server/wifi/WifiScanAlwaysAvailableSettingsCompatibility.java b/service/java/com/android/server/wifi/WifiScanAlwaysAvailableSettingsCompatibility.java
new file mode 100644
index 000000000..6abdd3162
--- /dev/null
+++ b/service/java/com/android/server/wifi/WifiScanAlwaysAvailableSettingsCompatibility.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2020 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 android.content.ContentResolver;
+import android.content.Context;
+import android.database.ContentObserver;
+import android.os.Handler;
+import android.provider.Settings;
+import android.util.Log;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+/**
+ * Note: This is a hack to provide backward compatibility with the
+ * {@link Settings.Global#WIFI_SCAN_ALWAYS_AVAILABLE} @hide settings usage. We migrated storage
+ * of the scan always available state from this setting to our internal storage, but need to support
+ * the existing @hide users.
+ * TODO(b/149954910): We should find a path to stop supporting this!
+ */
+public class WifiScanAlwaysAvailableSettingsCompatibility {
+ private static final String TAG = "WifiScanAlwaysAvailableSettingsCompatibility";
+
+ /**
+ * Copy of the settings string. Can't directly use the constant because it is @hide.
+ */
+ @VisibleForTesting
+ public static final String SETTINGS_GLOBAL_WIFI_SCAN_ALWAYS_AVAILABLE =
+ "wifi_scan_always_enabled";
+
+ private final Context mContext;
+ private final ContentResolver mContentResolver;
+ private final Handler mHandler;
+ private final WifiSettingsStore mWifiSettingsStore;
+ private final ActiveModeWarden mActiveModeWarden;
+ private final FrameworkFacade mFrameworkFacade;
+
+ public WifiScanAlwaysAvailableSettingsCompatibility(Context context,
+ Handler handler, WifiSettingsStore wifiSettingsStore,
+ ActiveModeWarden activeModeWarden, FrameworkFacade frameworkFacade) {
+ mContext = context;
+ mHandler = handler;
+ mWifiSettingsStore = wifiSettingsStore;
+ mActiveModeWarden = activeModeWarden;
+ mFrameworkFacade = frameworkFacade;
+
+ // Cache the content resolver to ensure that we can detect self changes.
+ mContentResolver = context.getContentResolver();
+ }
+
+ /**
+ * Register settings change observer.
+ */
+ public void initialize() {
+ ContentObserver contentObserver = new ContentObserver(mHandler) {
+ @Override
+ public void onChange(boolean selfChange) {
+ // Ignore any changes we triggered to avoid causing a loop.
+ if (selfChange) return;
+
+ boolean settingsIsAvailable =
+ mFrameworkFacade.getIntegerSetting(
+ mContentResolver, SETTINGS_GLOBAL_WIFI_SCAN_ALWAYS_AVAILABLE, 0)
+ == 1;
+ // Check if the new state is different from our current state.
+ if (mWifiSettingsStore.isScanAlwaysAvailable() != settingsIsAvailable) {
+ Log.i(TAG, "settings changed, new value: " + settingsIsAvailable
+ + ", triggering update");
+ mWifiSettingsStore.handleWifiScanAlwaysAvailableToggled(settingsIsAvailable);
+ mActiveModeWarden.scanAlwaysModeChanged();
+ }
+ }
+ };
+ mContentResolver.registerContentObserver(
+ Settings.Global.getUriFor(SETTINGS_GLOBAL_WIFI_SCAN_ALWAYS_AVAILABLE),
+ false, contentObserver);
+ }
+
+ /**
+ * Handle scan always available toggle from {@link android.net.wifi.WifiManager#
+ * setScanAlwaysAvailable(boolean)}
+ */
+ public void handleWifiScanAlwaysAvailableToggled(boolean isAvailable) {
+ mFrameworkFacade.setIntegerSetting(
+ mContentResolver, SETTINGS_GLOBAL_WIFI_SCAN_ALWAYS_AVAILABLE, isAvailable ? 1 : 0);
+ }
+}
diff --git a/service/java/com/android/server/wifi/WifiServiceImpl.java b/service/java/com/android/server/wifi/WifiServiceImpl.java
index e278c125e..acb060dfc 100644
--- a/service/java/com/android/server/wifi/WifiServiceImpl.java
+++ b/service/java/com/android/server/wifi/WifiServiceImpl.java
@@ -348,6 +348,7 @@ public class WifiServiceImpl extends BaseWifiService {
Log.i(TAG,
"WifiService starting up with Wi-Fi " + (wifiEnabled ? "enabled" : "disabled"));
+ mWifiInjector.getWifiScanAlwaysAvailableSettingsCompatibility().initialize();
mContext.registerReceiver(
new BroadcastReceiver() {
@Override
@@ -1893,6 +1894,8 @@ public class WifiServiceImpl extends BaseWifiService {
enforceNetworkSettingsPermission();
mLog.info("setScanAlwaysAvailable uid=%").c(Binder.getCallingUid()).flush();
mSettingsStore.handleWifiScanAlwaysAvailableToggled(isAvailable);
+ mWifiInjector.getWifiScanAlwaysAvailableSettingsCompatibility()
+ .handleWifiScanAlwaysAvailableToggled(isAvailable);
mActiveModeWarden.scanAlwaysModeChanged();
}
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiScanAlwaysAvailableSettingsCompatibilityTest.java b/tests/wifitests/src/com/android/server/wifi/WifiScanAlwaysAvailableSettingsCompatibilityTest.java
new file mode 100644
index 000000000..2caa813c6
--- /dev/null
+++ b/tests/wifitests/src/com/android/server/wifi/WifiScanAlwaysAvailableSettingsCompatibilityTest.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2020 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 com.android.server.wifi.WifiScanAlwaysAvailableSettingsCompatibility.SETTINGS_GLOBAL_WIFI_SCAN_ALWAYS_AVAILABLE;
+
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.validateMockitoUsage;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.database.ContentObserver;
+import android.os.Handler;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+/**
+ * Unit tests for {@link com.android.server.wifi.WifiScanAlwaysAvailableSettingsCompatibility}.
+ */
+@SmallTest
+public class WifiScanAlwaysAvailableSettingsCompatibilityTest extends WifiBaseTest {
+ @Mock
+ private Context mContext;
+ @Mock
+ private Handler mHandler;
+ @Mock
+ private WifiSettingsStore mWifiSettingsStore;
+ @Mock
+ private ActiveModeWarden mActiveModeWarden;
+ @Mock
+ private FrameworkFacade mFrameworkFacade;
+ @Mock
+ private ContentResolver mContentResolver;
+
+ private ArgumentCaptor<ContentObserver> mContentObserverArgumentCaptor =
+ ArgumentCaptor.forClass(ContentObserver.class);
+
+ private WifiScanAlwaysAvailableSettingsCompatibility mScanAlwaysCompatibility;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+
+ when(mContext.getContentResolver()).thenReturn(mContentResolver);
+ mScanAlwaysCompatibility =
+ new WifiScanAlwaysAvailableSettingsCompatibility(mContext, mHandler,
+ mWifiSettingsStore, mActiveModeWarden, mFrameworkFacade);
+ }
+
+ /**
+ * Called after each test
+ */
+ @After
+ public void cleanup() {
+ validateMockitoUsage();
+ }
+
+ @Test
+ public void reactToContentObserverChanges() {
+ mScanAlwaysCompatibility.initialize();
+ verify(mContentResolver).registerContentObserver(
+ any(), anyBoolean(), mContentObserverArgumentCaptor.capture());
+
+ ContentObserver contentObserver = mContentObserverArgumentCaptor.getValue();
+ assertNotNull(contentObserver);
+
+ when(mWifiSettingsStore.isScanAlwaysAvailable()).thenReturn(false);
+ when(mFrameworkFacade.getIntegerSetting(
+ any(ContentResolver.class),
+ eq(SETTINGS_GLOBAL_WIFI_SCAN_ALWAYS_AVAILABLE),
+ anyInt()))
+ .thenReturn(1);
+ contentObserver.onChange(false);
+
+ verify(mWifiSettingsStore).handleWifiScanAlwaysAvailableToggled(true);
+ verify(mActiveModeWarden).scanAlwaysModeChanged();
+
+ when(mWifiSettingsStore.isScanAlwaysAvailable()).thenReturn(true);
+ when(mFrameworkFacade.getIntegerSetting(
+ any(ContentResolver.class),
+ eq(SETTINGS_GLOBAL_WIFI_SCAN_ALWAYS_AVAILABLE),
+ anyInt()))
+ .thenReturn(0);
+ contentObserver.onChange(false);
+
+ verify(mWifiSettingsStore).handleWifiScanAlwaysAvailableToggled(false);
+ verify(mActiveModeWarden, times(2)).scanAlwaysModeChanged();
+ }
+
+
+ @Test
+ public void changeSetting() {
+ mScanAlwaysCompatibility.initialize();
+
+ mScanAlwaysCompatibility.handleWifiScanAlwaysAvailableToggled(true);
+ verify(mFrameworkFacade).setIntegerSetting(
+ any(ContentResolver.class),
+ eq(SETTINGS_GLOBAL_WIFI_SCAN_ALWAYS_AVAILABLE),
+ eq(1));
+
+ mScanAlwaysCompatibility.handleWifiScanAlwaysAvailableToggled(false);
+ verify(mFrameworkFacade).setIntegerSetting(
+ any(ContentResolver.class),
+ eq(SETTINGS_GLOBAL_WIFI_SCAN_ALWAYS_AVAILABLE),
+ eq(0));
+ }
+}
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java b/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java
index 08380614d..f1e515b9c 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java
@@ -307,6 +307,7 @@ public class WifiServiceImplTest extends WifiBaseTest {
@Mock IOnWifiActivityEnergyInfoListener mOnWifiActivityEnergyInfoListener;
@Mock IWifiConnectedNetworkScorer mWifiConnectedNetworkScorer;
@Mock WifiSettingsConfigStore mWifiSettingsConfigStore;
+ @Mock WifiScanAlwaysAvailableSettingsCompatibility mScanAlwaysAvailableSettingsCompatibility;
WifiLog mLog = new LogcatLog(TAG);
@@ -380,6 +381,8 @@ public class WifiServiceImplTest extends WifiBaseTest {
when(mWifiInjector.getWifiThreadRunner())
.thenReturn(new WifiThreadRunner(new Handler(mLooper.getLooper())));
when(mWifiInjector.getSettingsConfigStore()).thenReturn(mWifiSettingsConfigStore);
+ when(mWifiInjector.getWifiScanAlwaysAvailableSettingsCompatibility())
+ .thenReturn(mScanAlwaysAvailableSettingsCompatibility);
when(mClientModeImpl.syncStartSubscriptionProvisioning(anyInt(),
any(OsuProvider.class), any(IProvisioningCallback.class), any())).thenReturn(true);
// Create an OSU provider that can be provisioned via an open OSU AP
diff --git a/tests/wifitests/src/com/android/server/wifi/util/WifiPermissionsUtilTest.java b/tests/wifitests/src/com/android/server/wifi/util/WifiPermissionsUtilTest.java
index 7f6e1e1cd..799df547b 100644
--- a/tests/wifitests/src/com/android/server/wifi/util/WifiPermissionsUtilTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/util/WifiPermissionsUtilTest.java
@@ -1224,17 +1224,17 @@ public class WifiPermissionsUtilTest extends WifiBaseTest {
doThrow(new RuntimeException()).when(mLocationManager).isLocationEnabledForUser(any());
when(mMockFrameworkFacade.getIntegerSetting(
- any(), eq(Settings.Secure.LOCATION_MODE), anyInt()))
+ any(Context.class), eq(Settings.Secure.LOCATION_MODE), anyInt()))
.thenReturn(Settings.Secure.LOCATION_MODE_OFF);
assertFalse(codeUnderTest.isLocationModeEnabled());
when(mMockFrameworkFacade.getIntegerSetting(
- any(), eq(Settings.Secure.LOCATION_MODE), anyInt()))
+ any(Context.class), eq(Settings.Secure.LOCATION_MODE), anyInt()))
.thenReturn(Settings.Secure.LOCATION_MODE_ON);
assertTrue(codeUnderTest.isLocationModeEnabled());
verify(mMockFrameworkFacade, times(2)).getIntegerSetting(
- any(), eq(Settings.Secure.LOCATION_MODE), anyInt());
+ any(Context.class), eq(Settings.Secure.LOCATION_MODE), anyInt());
}
private Answer<Integer> createPermissionAnswer() {