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

Commit eadf1959 authored by Lorenzo Colitti's avatar Lorenzo Colitti Committed by Android (Google) Code Review
Browse files

Merge "Track IP addresses in WifiStateMachine." into klp-dev

parents 86974463 34b2b9b6
Loading
Loading
Loading
Loading
+151 −34
Original line number Diff line number Diff line
@@ -51,6 +51,7 @@ import android.net.LinkProperties;
import android.net.NetworkInfo;
import android.net.NetworkInfo.DetailedState;
import android.net.NetworkUtils;
import android.net.RouteInfo;
import android.net.wifi.WpsResult.Status;
import android.net.wifi.p2p.WifiP2pManager;
import android.net.wifi.p2p.WifiP2pService;
@@ -79,9 +80,12 @@ import com.android.internal.util.Protocol;
import com.android.internal.util.State;
import com.android.internal.util.StateMachine;

import com.android.server.net.BaseNetworkObserver;

import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Inet6Address;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
@@ -198,8 +202,19 @@ public class WifiStateMachine extends StateMachine {
    /* Tracks sequence number on a driver time out */
    private int mDriverStartToken = 0;

    /**
     * The link properties of the wifi interface.
     * Do not modify this directly; use updateLinkProperties instead.
     */
    private LinkProperties mLinkProperties;

    /**
     * Subset of link properties coming from netlink.
     * Currently includes IPv4 and IPv6 addresses. In the future will also include IPv6 DNS servers
     * and domains obtained from router advertisements (RFC 6106).
     */
    private final LinkProperties mNetlinkLinkProperties;

    /* Tracks sequence number on a periodic scan message */
    private int mPeriodicScanToken = 0;

@@ -215,6 +230,39 @@ public class WifiStateMachine extends StateMachine {
    private SupplicantStateTracker mSupplicantStateTracker;
    private DhcpStateMachine mDhcpStateMachine;

    private class InterfaceObserver extends BaseNetworkObserver {
        private WifiStateMachine mWifiStateMachine;

        InterfaceObserver(WifiStateMachine wifiStateMachine) {
            super();
            mWifiStateMachine = wifiStateMachine;
        }

        @Override
        public void addressUpdated(String address, String iface, int flags, int scope) {
            if (mWifiStateMachine.mInterfaceName.equals(iface)) {
                if (DBG) {
                    log("addressUpdated: " + address + " on " + iface +
                        " flags " + flags + " scope " + scope);
                }
                mWifiStateMachine.sendMessage(CMD_IP_ADDRESS_UPDATED, new LinkAddress(address));
            }
        }

        @Override
        public void addressRemoved(String address, String iface, int flags, int scope) {
            if (mWifiStateMachine.mInterfaceName.equals(iface)) {
                if (DBG) {
                    log("addressRemoved: " + address + " on " + iface +
                        " flags " + flags + " scope " + scope);
                }
                mWifiStateMachine.sendMessage(CMD_IP_ADDRESS_REMOVED, new LinkAddress(address));
            }
        }
    }

    private InterfaceObserver mInterfaceObserver;

    private AlarmManager mAlarmManager;
    private PendingIntent mScanIntent;
    private PendingIntent mDriverStopIntent;
@@ -372,6 +420,12 @@ public class WifiStateMachine extends StateMachine {
    public static final int CMD_START_NEXT_BATCHED_SCAN   = BASE + 136;
    public static final int CMD_POLL_BATCHED_SCAN         = BASE + 137;

    /* Link configuration (IP address, DNS, ...) changes */
    /* An new IP address was added to our interface, or an existing IP address was updated */
    static final int CMD_IP_ADDRESS_UPDATED               = BASE + 140;
    /* An IP address was removed from our interface */
    static final int CMD_IP_ADDRESS_REMOVED               = BASE + 141;

    public static final int CONNECT_MODE                   = 1;
    public static final int SCAN_ONLY_MODE                 = 2;
    public static final int SCAN_ONLY_WITH_WIFI_OFF_MODE   = 3;
@@ -585,15 +639,22 @@ public class WifiStateMachine extends StateMachine {
        mSupplicantStateTracker = new SupplicantStateTracker(context, this, mWifiConfigStore,
                getHandler());
        mLinkProperties = new LinkProperties();
        mNetlinkLinkProperties = new LinkProperties();

        mWifiP2pManager = (WifiP2pManager) mContext.getSystemService(Context.WIFI_P2P_SERVICE);

        mNetworkInfo.setIsAvailable(false);
        mLinkProperties.clear();
        mLastBssid = null;
        mLastNetworkId = WifiConfiguration.INVALID_NETWORK_ID;
        mLastSignalLevel = -1;

        mInterfaceObserver = new InterfaceObserver(this);
        try {
            mNwService.registerObserver(mInterfaceObserver);
        } catch (RemoteException e) {
            loge("Couldn't register interface observer: " + e.toString());
        }

        mAlarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
        Intent scanIntent = new Intent(ACTION_START_SCAN, null);
        mScanIntent = PendingIntent.getBroadcast(mContext, SCAN_REQUEST, scanIntent, 0);
@@ -1906,19 +1967,82 @@ public class WifiStateMachine extends StateMachine {
        }
    }

    private void configureLinkProperties() {
        if (mWifiConfigStore.isUsingStaticIp(mLastNetworkId)) {
            mLinkProperties = mWifiConfigStore.getLinkProperties(mLastNetworkId);
        } else {
    /**
     * Updates mLinkProperties by merging information from various sources.
     *
     * This is needed because the information in mLinkProperties comes from multiple sources (DHCP,
     * netlink, static configuration, ...). When one of these sources of information has updated
     * link properties, we can't just assign them to mLinkProperties or we'd lose track of the
     * information that came from other sources. Instead, when one of those sources has new
     * information, we update the object that tracks the information from that source and then
     * call this method to apply the change to mLinkProperties.
     *
     * The information in mLinkProperties is currently obtained as follows:
     * - Interface name: set in the constructor.
     * - IPv4 and IPv6 addresses: netlink, via mInterfaceObserver.
     * - IPv4 routes, DNS servers, and domains: DHCP.
     * - HTTP proxy: the wifi config store.
     */
    private void updateLinkProperties() {
        LinkProperties newLp = new LinkProperties();

        // Interface name and proxy are locally configured.
        newLp.setInterfaceName(mInterfaceName);
        newLp.setHttpProxy(mWifiConfigStore.getProxyProperties(mLastNetworkId));

        // IPv4 and IPv6 addresses come from netlink.
        newLp.setLinkAddresses(mNetlinkLinkProperties.getLinkAddresses());

        // For now, routing and DNS only come from DHCP or static configuration. In the future,
        // we'll need to merge IPv6 DNS servers and domains coming from netlink.
        synchronized (mDhcpResultsLock) {
            // Even when we're using static configuration, we don't need to look at the config
            // store, because static IP configuration also populates mDhcpResults.
            if ((mDhcpResults != null) && (mDhcpResults.linkProperties != null)) {
                    mLinkProperties = mDhcpResults.linkProperties;
                LinkProperties lp = mDhcpResults.linkProperties;
                for (RouteInfo route: lp.getRoutes()) {
                    newLp.addRoute(route);
                }
                for (InetAddress dns: lp.getDnses()) {
                    newLp.addDns(dns);
                }
            mLinkProperties.setHttpProxy(mWifiConfigStore.getProxyProperties(mLastNetworkId));
                newLp.setDomains(lp.getDomains());
            }
        mLinkProperties.setInterfaceName(mInterfaceName);
        if (DBG) log("netId=" + mLastNetworkId  + " Link configured: " + mLinkProperties);
        }

        // If anything has changed, and we're already connected, send out a notification.
        // If we're still connecting, apps will be notified when we connect.
        if (!newLp.equals(mLinkProperties)) {
            if (DBG) {
                log("Link configuration changed for netId: " + mLastNetworkId
                        + " old: " + mLinkProperties + "new: " + newLp);
            }
            mLinkProperties = newLp;
            if (getNetworkDetailedState() == DetailedState.CONNECTED) {
                sendLinkConfigurationChangedBroadcast();
            }
        }
    }

    /**
     * Clears all our link properties.
     */
    private void clearLinkProperties() {
        // If the network used DHCP, clear the LinkProperties we stored in the config store.
        if (!mWifiConfigStore.isUsingStaticIp(mLastNetworkId)) {
            mWifiConfigStore.clearLinkProperties(mLastNetworkId);
        }

        // Clear the link properties obtained from DHCP and netlink.
        synchronized(mDhcpResultsLock) {
            if (mDhcpResults != null && mDhcpResults.linkProperties != null) {
                mDhcpResults.linkProperties.clear();
            }
        }
        mNetlinkLinkProperties.clear();

        // Now clear the merged link properties.
        mLinkProperties.clear();
    }

    private int getMaxDhcpRetries() {
@@ -2041,16 +2165,11 @@ public class WifiStateMachine extends StateMachine {
        mWifiConfigStore.updateStatus(mLastNetworkId, DetailedState.DISCONNECTED);

        /* Clear network properties */
        mLinkProperties.clear();
        clearLinkProperties();

        /* send event to CM & network change broadcast */
        sendNetworkStateChangeBroadcast(mLastBssid);

        /* Clear IP settings if the network used DHCP */
        if (!mWifiConfigStore.isUsingStaticIp(mLastNetworkId)) {
            mWifiConfigStore.clearLinkProperties(mLastNetworkId);
        }

        mLastBssid= null;
        mLastNetworkId = WifiConfiguration.INVALID_NETWORK_ID;
    }
@@ -2149,20 +2268,7 @@ public class WifiStateMachine extends StateMachine {
        }
        mWifiInfo.setInetAddress(addr);
        mWifiInfo.setMeteredHint(dhcpResults.hasMeteredHint());
        if (getNetworkDetailedState() == DetailedState.CONNECTED) {
            //DHCP renewal in connected state
            linkProperties.setHttpProxy(mWifiConfigStore.getProxyProperties(mLastNetworkId));
            if (!linkProperties.equals(mLinkProperties)) {
                if (DBG) {
                    log("Link configuration changed for netId: " + mLastNetworkId
                            + " old: " + mLinkProperties + "new: " + linkProperties);
                }
                mLinkProperties = linkProperties;
                sendLinkConfigurationChangedBroadcast();
            }
        } else {
            configureLinkProperties();
        }
        updateLinkProperties();
    }

    private void handleFailedIpConfiguration() {
@@ -2387,6 +2493,17 @@ public class WifiStateMachine extends StateMachine {
                    mTemporarilyDisconnectWifi = (message.arg1 == 1);
                    replyToMessage(message, WifiP2pService.DISCONNECT_WIFI_RESPONSE);
                    break;
                case CMD_IP_ADDRESS_UPDATED:
                    // addLinkAddress is a no-op if called more than once with the same address.
                    if (mNetlinkLinkProperties.addLinkAddress((LinkAddress) message.obj)) {
                        updateLinkProperties();
                    }
                    break;
                case CMD_IP_ADDRESS_REMOVED:
                    if (mNetlinkLinkProperties.removeLinkAddress((LinkAddress) message.obj)) {
                        updateLinkProperties();
                    }
                    break;
                default:
                    loge("Error! unhandled message" + message);
                    break;
@@ -3405,8 +3522,7 @@ public class WifiStateMachine extends StateMachine {
                        }
                        if (result.hasProxyChanged()) {
                            log("Reconfiguring proxy on connection");
                            configureLinkProperties();
                            sendLinkConfigurationChangedBroadcast();
                            updateLinkProperties();
                        }
                    }

@@ -3460,13 +3576,14 @@ public class WifiStateMachine extends StateMachine {
        @Override
        public void enter() {
            if (!mWifiConfigStore.isUsingStaticIp(mLastNetworkId)) {
                // TODO: If we're switching between static IP configuration and DHCP, remove the
                // static configuration first.
                startDhcp();
            } else {
                // stop any running dhcp before assigning static IP
                stopDhcp();
                DhcpResults dhcpResults = new DhcpResults(
                        mWifiConfigStore.getLinkProperties(mLastNetworkId));
                dhcpResults.linkProperties.setInterfaceName(mInterfaceName);
                InterfaceConfiguration ifcg = new InterfaceConfiguration();
                Iterator<LinkAddress> addrs =
                        dhcpResults.linkProperties.getLinkAddresses().iterator();