Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 165c51c0 authored by Lorenzo Colitti's avatar Lorenzo Colitti
Browse files

Support "don't ask again" in the avoid bad wifi dialog.

This contains the following changes:

1. Make NETWORK_AVOID_BAD_WIFI a tristate: 0 means never avoid
   bad wifi, unset means prompt the user, 1 means always avoid.
2. Look at NETWORK_AVOID_BAD_WIFI only if the carrier restricts
   avoiding bad wifi (previously, we relied on the setting being
   null and defaulting to the value of the config variable).
3. Add an avoidUnvalidated bit to NetworkAgentInfo to track
   whether the user has requested switching away from this
   unvalidated network even though avoiding bad wifi is generally
   disabled. This is set to true when the user selects "switch"
   in the dialog without setting the "Don't ask again" checkbox.
4. Add a hidden setAvoidUnvalidated API to ConnectivityManager to
   set the avoidUnvalidated bit.
5. Additional unit test coverage.

Bug: 31075769
Change-Id: I1be60c3016c8095df3c4752330149ce638bd0ce1
parent 5883cd46
Loading
Loading
Loading
Loading
+21 −0
Original line number Diff line number Diff line
@@ -3197,6 +3197,27 @@ public class ConnectivityManager {
        }
    }

    /**
     * Informs the system to penalize {@code network}'s score when it becomes unvalidated. This is
     * only meaningful if the system is configured not to penalize such networks, e.g., if the
     * {@code config_networkAvoidBadWifi} configuration variable is set to 0 and the {@code
     * NETWORK_AVOID_BAD_WIFI setting is unset}.
     *
     * <p>This method requires the caller to hold the permission
     * {@link android.Manifest.permission#CONNECTIVITY_INTERNAL}
     *
     * @param network The network to accept.
     *
     * @hide
     */
    public void setAvoidUnvalidated(Network network) {
        try {
            mService.setAvoidUnvalidated(network);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Resets all connectivity manager settings back to factory defaults.
     * @hide
+1 −0
Original line number Diff line number Diff line
@@ -161,6 +161,7 @@ interface IConnectivityManager
    void releaseNetworkRequest(in NetworkRequest networkRequest);

    void setAcceptUnvalidated(in Network network, boolean accept, boolean always);
    void setAvoidUnvalidated(in Network network);

    int getRestoreDefaultNetworkDelay(int networkType);

+7 −0
Original line number Diff line number Diff line
@@ -7443,6 +7443,13 @@ public final class Settings {

       /**
        * Whether to automatically switch away from wifi networks that lose Internet access.
        * Only meaningful if config_networkAvoidBadWifi is set to 0, otherwise the system always
        * avoids such networks. Valid values are:
        *
        * 0: Don't avoid bad wifi, don't prompt the user. Get stuck on bad wifi like it's 2013.
        * null: Ask the user whether to switch away from bad wifi.
        * 1: Avoid bad wifi.
        *
        * @hide
        */
       public static final String NETWORK_AVOID_BAD_WIFI = "network_avoid_bad_wifi";
+47 −15
Original line number Diff line number Diff line
@@ -365,6 +365,11 @@ public class ConnectivityService extends IConnectivityManager.Stub
     */
    private static final int EVENT_SET_ACCEPT_UNVALIDATED = 28;

    /**
     * used to specify whether a network should not be penalized when it becomes unvalidated.
     */
    private static final int EVENT_SET_AVOID_UNVALIDATED = 35;

    /**
     * used to ask the user to confirm a connection to an unvalidated network.
     * obj  = network
@@ -2681,6 +2686,12 @@ public class ConnectivityService extends IConnectivityManager.Stub
                accept ? 1 : 0, always ? 1: 0, network));
    }

    @Override
    public void setAvoidUnvalidated(Network network) {
        enforceConnectivityInternalPermission();
        mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_AVOID_UNVALIDATED, network));
    }

    private void handleSetAcceptUnvalidated(Network network, boolean accept, boolean always) {
        if (DBG) log("handleSetAcceptUnvalidated network=" + network +
                " accept=" + accept + " always=" + always);
@@ -2721,6 +2732,20 @@ public class ConnectivityService extends IConnectivityManager.Stub

    }

    private void handleSetAvoidUnvalidated(Network network) {
        NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
        if (nai == null || nai.lastValidated) {
            // Nothing to do. The network either disconnected or revalidated.
            return;
        }
        if (!nai.avoidUnvalidated) {
            int oldScore = nai.getCurrentScore();
            nai.avoidUnvalidated = true;
            rematchAllNetworksAndRequests(nai, oldScore);
            sendUpdatedScoreToFactories(nai);
        }
    }

    private void scheduleUnvalidatedPrompt(NetworkAgentInfo nai) {
        if (VDBG) log("scheduleUnvalidatedPrompt " + nai.network);
        mHandler.sendMessageDelayed(
@@ -2728,28 +2753,31 @@ public class ConnectivityService extends IConnectivityManager.Stub
                PROMPT_UNVALIDATED_DELAY_MS);
    }

    private boolean mAvoidBadWifi;
    private boolean mAvoidBadWifi = true;

    public boolean avoidBadWifi() {
        return mAvoidBadWifi;
    }

    @VisibleForTesting
    public boolean updateAvoidBadWifi() {
        // There are two modes: either we always automatically avoid unvalidated wifi, or we show a
        // dialog and don't switch to it. The behaviour is controlled by the NETWORK_AVOID_BAD_WIFI
        // setting. If the setting has no value, then the value is taken from the config value,
        // which can be changed via OEM/carrier overlays.
        //
        // The only valid values for NETWORK_AVOID_BAD_WIFI are null and unset. Currently, the unit
        // test uses 0 in order to avoid having to mock out fetching the carrier setting.
        int defaultAvoidBadWifi =
            mContext.getResources().getInteger(R.integer.config_networkAvoidBadWifi);
        int avoid = Settings.Global.getInt(mContext.getContentResolver(),
            Settings.Global.NETWORK_AVOID_BAD_WIFI, defaultAvoidBadWifi);
    /** Whether the device or carrier configuration disables avoiding bad wifi by default. */
    public boolean configRestrictsAvoidBadWifi() {
        return mContext.getResources().getInteger(R.integer.config_networkAvoidBadWifi) == 0;
    }

    /** Whether we should display a notification when wifi becomes unvalidated. */
    public boolean shouldNotifyWifiUnvalidated() {
        return configRestrictsAvoidBadWifi() &&
                Settings.Global.getString(mContext.getContentResolver(),
                        Settings.Global.NETWORK_AVOID_BAD_WIFI) == null;
    }

    private boolean updateAvoidBadWifi() {
        boolean settingAvoidBadWifi = "1".equals(Settings.Global.getString(
                mContext.getContentResolver(), Settings.Global.NETWORK_AVOID_BAD_WIFI));

        boolean prev = mAvoidBadWifi;
        mAvoidBadWifi = (avoid == 1);
        mAvoidBadWifi = settingAvoidBadWifi || !configRestrictsAvoidBadWifi();
        return mAvoidBadWifi != prev;
    }

@@ -2802,7 +2830,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
        NetworkCapabilities nc = nai.networkCapabilities;
        if (DBG) log("handleNetworkUnvalidated " + nai.name() + " cap=" + nc);

        if (nc.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) && !avoidBadWifi()) {
        if (nc.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) && shouldNotifyWifiUnvalidated()) {
            showValidationNotification(nai, NotificationType.LOST_INTERNET);
        }
    }
@@ -2880,6 +2908,10 @@ public class ConnectivityService extends IConnectivityManager.Stub
                    handleSetAcceptUnvalidated((Network) msg.obj, msg.arg1 != 0, msg.arg2 != 0);
                    break;
                }
                case EVENT_SET_AVOID_UNVALIDATED: {
                    handleSetAvoidUnvalidated((Network) msg.obj);
                    break;
                }
                case EVENT_PROMPT_UNVALIDATED: {
                    handlePromptUnvalidated((Network) msg.obj);
                    break;
+10 −6
Original line number Diff line number Diff line
@@ -138,12 +138,14 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> {
    public boolean everValidated;

    // The result of the last validation attempt on this network (true if validated, false if not).
    // This bit exists only because we never unvalidate a network once it's been validated, and that
    // is because the network scoring and revalidation code does not (may not?) deal properly with
    // networks becoming unvalidated.
    // TODO: Fix the network scoring code, remove this, and rename everValidated to validated.
    public boolean lastValidated;

    // If true, becoming unvalidated will lower the network's score. This is only meaningful if the
    // system is configured not to do this for certain networks, e.g., if the
    // config_networkAvoidBadWifi option is set to 0 and the user has not overridden that via
    // Settings.Global.NETWORK_AVOID_BAD_WIFI.
    public boolean avoidUnvalidated;

    // Whether a captive portal was ever detected on this network.
    // This is a sticky bit; once set it is never cleared.
    public boolean everCaptivePortalDetected;
@@ -365,8 +367,10 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> {
    // Return true on devices configured to ignore score penalty for wifi networks
    // that become unvalidated (b/31075769).
    private boolean ignoreWifiUnvalidationPenalty() {
        boolean isWifi = networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI);
        return isWifi && !mConnService.avoidBadWifi() && everValidated;
        boolean isWifi = networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) &&
                networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
        boolean avoidBadWifi = mConnService.avoidBadWifi() || avoidUnvalidated;
        return isWifi && !avoidBadWifi && everValidated;
    }

    // Get the current score for this Network.  This may be modified from what the
Loading