Merge "Provide a way to override the avoid bad wifi configuration" am: 38e8c2c94b

Original change: https://android-review.googlesource.com/c/platform/packages/modules/Connectivity/+/1733788

Change-Id: I48af839ba2a8f2e7531aa9a897ad7a1d00f8a676
This commit is contained in:
Chiachang Wang
2021-06-23 02:07:45 +00:00
committed by Automerger Merge Worker
5 changed files with 119 additions and 25 deletions

View File

@@ -4712,6 +4712,22 @@ public class ConnectivityManager {
} }
} }
/**
* Temporarily allow bad wifi to override {@code config_networkAvoidBadWifi} configuration.
*
* @param timeMs The expired current time. The value should be set within a limited time from
* now.
*
* @hide
*/
public void setTestAllowBadWifiUntil(long timeMs) {
try {
mService.setTestAllowBadWifiUntil(timeMs);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/** /**
* Requests that the system open the captive portal app on the specified network. * Requests that the system open the captive portal app on the specified network.
* *

View File

@@ -226,4 +226,6 @@ interface IConnectivityManager
void offerNetwork(int providerId, in NetworkScore score, void offerNetwork(int providerId, in NetworkScore score,
in NetworkCapabilities caps, in INetworkOfferCallback callback); in NetworkCapabilities caps, in INetworkOfferCallback callback);
void unofferNetwork(in INetworkOfferCallback callback); void unofferNetwork(in INetworkOfferCallback callback);
void setTestAllowBadWifiUntil(long timeMs);
} }

View File

@@ -75,6 +75,7 @@ public class MultinetworkPolicyTracker {
private volatile boolean mAvoidBadWifi = true; private volatile boolean mAvoidBadWifi = true;
private volatile int mMeteredMultipathPreference; private volatile int mMeteredMultipathPreference;
private int mActiveSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; private int mActiveSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
private volatile long mTestAllowBadWifiUntilMs = 0;
// Mainline module can't use internal HandlerExecutor, so add an identical executor here. // Mainline module can't use internal HandlerExecutor, so add an identical executor here.
private static class HandlerExecutor implements Executor { private static class HandlerExecutor implements Executor {
@@ -162,14 +163,31 @@ public class MultinetworkPolicyTracker {
* Whether the device or carrier configuration disables avoiding bad wifi by default. * Whether the device or carrier configuration disables avoiding bad wifi by default.
*/ */
public boolean configRestrictsAvoidBadWifi() { public boolean configRestrictsAvoidBadWifi() {
final boolean allowBadWifi = mTestAllowBadWifiUntilMs > 0
&& mTestAllowBadWifiUntilMs > System.currentTimeMillis();
// If the config returns true, then avoid bad wifi design can be controlled by the
// NETWORK_AVOID_BAD_WIFI setting.
if (allowBadWifi) return true;
// TODO: use R.integer.config_networkAvoidBadWifi directly // TODO: use R.integer.config_networkAvoidBadWifi directly
final int id = mResources.get().getIdentifier("config_networkAvoidBadWifi", final int id = mResources.get().getIdentifier("config_networkAvoidBadWifi",
"integer", mResources.getResourcesContext().getPackageName()); "integer", mResources.getResourcesContext().getPackageName());
return (getResourcesForActiveSubId().getInteger(id) == 0); return (getResourcesForActiveSubId().getInteger(id) == 0);
} }
/**
* Temporarily allow bad wifi to override {@code config_networkAvoidBadWifi} configuration.
* The value works when the time set is more than {@link System.currentTimeMillis()}.
*/
public void setTestAllowBadWifiUntil(long timeMs) {
Log.d(TAG, "setTestAllowBadWifiUntil: " + mTestAllowBadWifiUntilMs);
mTestAllowBadWifiUntilMs = timeMs;
updateAvoidBadWifi();
}
@VisibleForTesting
@NonNull @NonNull
private Resources getResourcesForActiveSubId() { protected Resources getResourcesForActiveSubId() {
return SubscriptionManager.getResourcesForSubId( return SubscriptionManager.getResourcesForSubId(
mResources.getResourcesContext(), mActiveSubId); mResources.getResourcesContext(), mActiveSubId);
} }

View File

@@ -650,6 +650,12 @@ public class ConnectivityService extends IConnectivityManager.Stub
*/ */
private static final int EVENT_MOBILE_DATA_PREFERRED_UIDS_CHANGED = 54; private static final int EVENT_MOBILE_DATA_PREFERRED_UIDS_CHANGED = 54;
/**
* Event to set temporary allow bad wifi within a limited time to override
* {@code config_networkAvoidBadWifi}.
*/
private static final int EVENT_SET_TEST_ALLOW_BAD_WIFI_UNTIL = 55;
/** /**
* Argument for {@link #EVENT_PROVISIONING_NOTIFICATION} to indicate that the notification * Argument for {@link #EVENT_PROVISIONING_NOTIFICATION} to indicate that the notification
* should be shown. * should be shown.
@@ -662,6 +668,11 @@ public class ConnectivityService extends IConnectivityManager.Stub
*/ */
private static final int PROVISIONING_NOTIFICATION_HIDE = 0; private static final int PROVISIONING_NOTIFICATION_HIDE = 0;
/**
* The maximum alive time to allow bad wifi configuration for testing.
*/
private static final long MAX_TEST_ALLOW_BAD_WIFI_UNTIL_MS = 5 * 60 * 1000L;
private static String eventName(int what) { private static String eventName(int what) {
return sMagicDecoderRing.get(what, Integer.toString(what)); return sMagicDecoderRing.get(what, Integer.toString(what));
} }
@@ -4334,6 +4345,22 @@ public class ConnectivityService extends IConnectivityManager.Stub
mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_AVOID_UNVALIDATED, network)); mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_AVOID_UNVALIDATED, network));
} }
@Override
public void setTestAllowBadWifiUntil(long timeMs) {
enforceSettingsPermission();
if (!Build.isDebuggable()) {
throw new IllegalStateException("Does not support in non-debuggable build");
}
if (timeMs > System.currentTimeMillis() + MAX_TEST_ALLOW_BAD_WIFI_UNTIL_MS) {
throw new IllegalArgumentException("It should not exceed "
+ MAX_TEST_ALLOW_BAD_WIFI_UNTIL_MS + "ms from now");
}
mHandler.sendMessage(
mHandler.obtainMessage(EVENT_SET_TEST_ALLOW_BAD_WIFI_UNTIL, timeMs));
}
private void handleSetAcceptUnvalidated(Network network, boolean accept, boolean always) { private void handleSetAcceptUnvalidated(Network network, boolean accept, boolean always) {
if (DBG) log("handleSetAcceptUnvalidated network=" + network + if (DBG) log("handleSetAcceptUnvalidated network=" + network +
" accept=" + accept + " always=" + always); " accept=" + accept + " always=" + always);
@@ -4876,6 +4903,10 @@ public class ConnectivityService extends IConnectivityManager.Stub
case EVENT_MOBILE_DATA_PREFERRED_UIDS_CHANGED: case EVENT_MOBILE_DATA_PREFERRED_UIDS_CHANGED:
handleMobileDataPreferredUidsChanged(); handleMobileDataPreferredUidsChanged();
break; break;
case EVENT_SET_TEST_ALLOW_BAD_WIFI_UNTIL:
final long timeMs = ((Long) msg.obj).longValue();
mMultinetworkPolicyTracker.setTestAllowBadWifiUntil(timeMs);
break;
} }
} }
} }

View File

@@ -1496,8 +1496,7 @@ public class ConnectivityServiceTest {
return mService.getNetworkAgentInfoForNetwork(mna.getNetwork()).clatd; return mService.getNetworkAgentInfoForNetwork(mna.getNetwork()).clatd;
} }
private static class WrappedMultinetworkPolicyTracker extends MultinetworkPolicyTracker { private class WrappedMultinetworkPolicyTracker extends MultinetworkPolicyTracker {
volatile boolean mConfigRestrictsAvoidBadWifi;
volatile int mConfigMeteredMultipathPreference; volatile int mConfigMeteredMultipathPreference;
WrappedMultinetworkPolicyTracker(Context c, Handler h, Runnable r) { WrappedMultinetworkPolicyTracker(Context c, Handler h, Runnable r) {
@@ -1505,8 +1504,8 @@ public class ConnectivityServiceTest {
} }
@Override @Override
public boolean configRestrictsAvoidBadWifi() { protected Resources getResourcesForActiveSubId() {
return mConfigRestrictsAvoidBadWifi; return mResources;
} }
@Override @Override
@@ -1723,7 +1722,9 @@ public class ConnectivityServiceTest {
.getIdentifier(eq("config_networkSupportedKeepaliveCount"), eq("array"), any()); .getIdentifier(eq("config_networkSupportedKeepaliveCount"), eq("array"), any());
doReturn(R.array.network_switch_type_name).when(mResources) doReturn(R.array.network_switch_type_name).when(mResources)
.getIdentifier(eq("network_switch_type_name"), eq("array"), any()); .getIdentifier(eq("network_switch_type_name"), eq("array"), any());
doReturn(R.integer.config_networkAvoidBadWifi).when(mResources)
.getIdentifier(eq("config_networkAvoidBadWifi"), eq("integer"), any());
doReturn(1).when(mResources).getInteger(R.integer.config_networkAvoidBadWifi);
final ConnectivityResources connRes = mock(ConnectivityResources.class); final ConnectivityResources connRes = mock(ConnectivityResources.class);
doReturn(mResources).when(connRes).get(); doReturn(mResources).when(connRes).get();
@@ -4645,30 +4646,29 @@ public class ConnectivityServiceTest {
} }
@Test @Test
public void testAvoidBadWifiSetting() throws Exception { public void testSetAllowBadWifiUntil() throws Exception {
runAsShell(NETWORK_SETTINGS,
() -> mService.setTestAllowBadWifiUntil(System.currentTimeMillis() + 5_000L));
waitForIdle();
testAvoidBadWifiConfig_controlledBySettings();
runAsShell(NETWORK_SETTINGS,
() -> mService.setTestAllowBadWifiUntil(System.currentTimeMillis() - 5_000L));
waitForIdle();
testAvoidBadWifiConfig_ignoreSettings();
}
private void testAvoidBadWifiConfig_controlledBySettings() {
final ContentResolver cr = mServiceContext.getContentResolver(); final ContentResolver cr = mServiceContext.getContentResolver();
final String settingName = ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI; final String settingName = ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI;
mPolicyTracker.mConfigRestrictsAvoidBadWifi = false; Settings.Global.putString(cr, settingName, "0");
String[] values = new String[] {null, "0", "1"};
for (int i = 0; i < values.length; i++) {
Settings.Global.putInt(cr, settingName, 1);
mPolicyTracker.reevaluate();
waitForIdle();
String msg = String.format("config=false, setting=%s", values[i]);
assertTrue(mService.avoidBadWifi());
assertFalse(msg, mPolicyTracker.shouldNotifyWifiUnvalidated());
}
mPolicyTracker.mConfigRestrictsAvoidBadWifi = true;
Settings.Global.putInt(cr, settingName, 0);
mPolicyTracker.reevaluate(); mPolicyTracker.reevaluate();
waitForIdle(); waitForIdle();
assertFalse(mService.avoidBadWifi()); assertFalse(mService.avoidBadWifi());
assertFalse(mPolicyTracker.shouldNotifyWifiUnvalidated()); assertFalse(mPolicyTracker.shouldNotifyWifiUnvalidated());
Settings.Global.putInt(cr, settingName, 1); Settings.Global.putString(cr, settingName, "1");
mPolicyTracker.reevaluate(); mPolicyTracker.reevaluate();
waitForIdle(); waitForIdle();
assertTrue(mService.avoidBadWifi()); assertTrue(mService.avoidBadWifi());
@@ -4681,13 +4681,40 @@ public class ConnectivityServiceTest {
assertTrue(mPolicyTracker.shouldNotifyWifiUnvalidated()); assertTrue(mPolicyTracker.shouldNotifyWifiUnvalidated());
} }
private void testAvoidBadWifiConfig_ignoreSettings() {
final ContentResolver cr = mServiceContext.getContentResolver();
final String settingName = ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI;
String[] values = new String[] {null, "0", "1"};
for (int i = 0; i < values.length; i++) {
Settings.Global.putString(cr, settingName, values[i]);
mPolicyTracker.reevaluate();
waitForIdle();
String msg = String.format("config=false, setting=%s", values[i]);
assertTrue(mService.avoidBadWifi());
assertFalse(msg, mPolicyTracker.shouldNotifyWifiUnvalidated());
}
}
@Test
public void testAvoidBadWifiSetting() throws Exception {
final ContentResolver cr = mServiceContext.getContentResolver();
final String settingName = ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI;
doReturn(1).when(mResources).getInteger(R.integer.config_networkAvoidBadWifi);
testAvoidBadWifiConfig_ignoreSettings();
doReturn(0).when(mResources).getInteger(R.integer.config_networkAvoidBadWifi);
testAvoidBadWifiConfig_controlledBySettings();
}
@Ignore("Refactoring in progress b/178071397") @Ignore("Refactoring in progress b/178071397")
@Test @Test
public void testAvoidBadWifi() throws Exception { public void testAvoidBadWifi() throws Exception {
final ContentResolver cr = mServiceContext.getContentResolver(); final ContentResolver cr = mServiceContext.getContentResolver();
// Pretend we're on a carrier that restricts switching away from bad wifi. // Pretend we're on a carrier that restricts switching away from bad wifi.
mPolicyTracker.mConfigRestrictsAvoidBadWifi = true; doReturn(0).when(mResources).getInteger(R.integer.config_networkAvoidBadWifi);
// File a request for cell to ensure it doesn't go down. // File a request for cell to ensure it doesn't go down.
final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback(); final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
@@ -4738,13 +4765,13 @@ public class ConnectivityServiceTest {
// Simulate switching to a carrier that does not restrict avoiding bad wifi, and expect // Simulate switching to a carrier that does not restrict avoiding bad wifi, and expect
// that we switch back to cell. // that we switch back to cell.
mPolicyTracker.mConfigRestrictsAvoidBadWifi = false; doReturn(1).when(mResources).getInteger(R.integer.config_networkAvoidBadWifi);
mPolicyTracker.reevaluate(); mPolicyTracker.reevaluate();
defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent); defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
assertEquals(mCm.getActiveNetwork(), cellNetwork); assertEquals(mCm.getActiveNetwork(), cellNetwork);
// Switch back to a restrictive carrier. // Switch back to a restrictive carrier.
mPolicyTracker.mConfigRestrictsAvoidBadWifi = true; doReturn(0).when(mResources).getInteger(R.integer.config_networkAvoidBadWifi);
mPolicyTracker.reevaluate(); mPolicyTracker.reevaluate();
defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
assertEquals(mCm.getActiveNetwork(), wifiNetwork); assertEquals(mCm.getActiveNetwork(), wifiNetwork);