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

Commit fa57c489 authored by Lorenzo Colitti's avatar Lorenzo Colitti
Browse files

Allow apps with ACCESS_WIFI_STATE to listen for wifi networks

The compatibility measure introduced in bug 20081183 for apps
that connect to a Wi-Fi network without Internet access and then
expect to be able to use that network requires that such apps
register a NetworkCallback so that their WifiManager can pin them
to whatever wifi Network connects.

Currently, registering the callback requires ACCESS_NETWORK_STATE
and the app may not have that permission. Allow registering wifi
(only) callbacks if the app has ACCESS_WIFI_STATE.

If the app does not have ACCESS_WIFI_STATE (unlikely, since
CHANGE_WIFI_STATE is not very useful without ACCESS_WIFI_STATE),
then don't enable the compatibility measure.

Bug: 20081183
Bug: 20423580
Change-Id: Iad328d30c2d170dead883868fece3d922da68f6f
parent 8b625dbe
Loading
Loading
Loading
Loading
+25 −1
Original line number Diff line number Diff line
@@ -3518,10 +3518,34 @@ public class ConnectivityService extends IConnectivityManager.Stub
                getCallingUid(), 0, operation));
    }

    // In order to implement the compatibility measure for pre-M apps that call
    // WifiManager.enableNetwork(..., true) without also binding to that network explicitly,
    // WifiManager registers a network listen for the purpose of calling setProcessDefaultNetwork.
    // This ensures it has permission to do so.
    private boolean hasWifiNetworkListenPermission(NetworkCapabilities nc) {
        if (nc == null) {
            return false;
        }
        int[] transportTypes = nc.getTransportTypes();
        if (transportTypes.length != 1 || transportTypes[0] != NetworkCapabilities.TRANSPORT_WIFI) {
            return false;
        }
        try {
            mContext.enforceCallingOrSelfPermission(
                    android.Manifest.permission.ACCESS_WIFI_STATE,
                    "ConnectivityService");
        } catch (SecurityException e) {
            return false;
        }
        return true;
    }

    @Override
    public NetworkRequest listenForNetwork(NetworkCapabilities networkCapabilities,
            Messenger messenger, IBinder binder) {
        if (!hasWifiNetworkListenPermission(networkCapabilities)) {
            enforceAccessPermission();
        }

        NetworkRequest networkRequest = new NetworkRequest(new NetworkCapabilities(
                networkCapabilities), TYPE_NONE, nextNetworkRequestId());
+10 −2
Original line number Diff line number Diff line
@@ -2063,7 +2063,11 @@ public class WifiManager {
                        .removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
                        .build();
                mNetworkCallback = new PinningNetworkCallback();
                try {
                    sCM.registerNetworkCallback(request, mNetworkCallback);
                } catch (SecurityException e) {
                    Log.d(TAG, "Failed to register network callback", e);
                }
            }
        }
    }
@@ -2072,7 +2076,11 @@ public class WifiManager {
        initConnectivityManager();
        synchronized (sCM) {
            if (mNetworkCallback != null) {
                try {
                    sCM.unregisterNetworkCallback(mNetworkCallback);
                } catch (SecurityException e) {
                    Log.d(TAG, "Failed to unregister network callback", e);
                }
                mNetworkCallback = null;
            }
        }