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

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

Notify network observers of route changes.

Bug: 9180552
Change-Id: If8432bc74335676320b815784b21f404d3479c35
parent 10accbb4
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package android.net;

import android.net.LinkAddress;
import android.net.RouteInfo;

/**
 * Callback class for receiving events from an INetworkManagementService
@@ -98,4 +99,14 @@ interface INetworkManagementEventObserver {
     * @param servers The IP addresses of the DNS servers.
     */
    void interfaceDnsServerInfo(String iface, long lifetime, in String[] servers);

    /**
     * A route has been added or updated.
     */
    void routeUpdated(in RouteInfo route);

    /**
     * A route has been removed.
     */
    void routeRemoved(in RouteInfo route);
}
+11 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.server.net;

import android.net.INetworkManagementEventObserver;
import android.net.LinkAddress;
import android.net.RouteInfo;

/**
 * Base {@link INetworkManagementEventObserver} that provides no-op
@@ -70,4 +71,14 @@ public class BaseNetworkObserver extends INetworkManagementEventObserver.Stub {
    public void interfaceDnsServerInfo(String iface, long lifetime, String[] servers) {
        // default no-op
    }

    @Override
    public void routeUpdated(RouteInfo route) {
        // default no-op
    }

    @Override
    public void routeRemoved(RouteInfo route) {
        // default no-op
    }
}
+35 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.server.net;

import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.RouteInfo;
import android.util.Log;

/**
@@ -84,6 +85,12 @@ public class NetlinkTracker extends BaseNetworkObserver {
        }
    }

    private void maybeLog(String operation, Object o) {
        if (DBG) {
            Log.d(TAG, operation + ": " + o.toString());
        }
    }

    @Override
    public void addressUpdated(String iface, LinkAddress address) {
        if (mInterfaceName.equals(iface)) {
@@ -112,6 +119,34 @@ public class NetlinkTracker extends BaseNetworkObserver {
        }
    }

    @Override
    public void routeUpdated(RouteInfo route) {
        if (mInterfaceName.equals(route.getInterface())) {
            maybeLog("routeUpdated", route);
            boolean changed;
            synchronized (this) {
                changed = mLinkProperties.addRoute(route);
            }
            if (changed) {
                mCallback.update();
            }
        }
    }

    @Override
    public void routeRemoved(RouteInfo route) {
        if (mInterfaceName.equals(route.getInterface())) {
            maybeLog("routeRemoved", route);
            boolean changed;
            synchronized (this) {
                changed = mLinkProperties.removeRoute(route);
            }
            if (changed) {
                mCallback.update();
            }
        }
    }

    /**
     * Returns a copy of this object's LinkProperties.
     */
+65 −0
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@ import android.content.Context;
import android.net.ConnectivityManager;
import android.net.INetworkManagementEventObserver;
import android.net.InterfaceConfiguration;
import android.net.IpPrefix;
import android.net.LinkAddress;
import android.net.NetworkStats;
import android.net.NetworkUtils;
@@ -145,6 +146,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub
        public static final int InterfaceClassActivity    = 613;
        public static final int InterfaceAddressChange    = 614;
        public static final int InterfaceDnsServerInfo    = 615;
        public static final int RouteChange               = 616;
    }

    static final int DAEMON_MSG_MOBILE_CONN_REAL_TIME_INFO = 1;
@@ -580,6 +582,28 @@ public class NetworkManagementService extends INetworkManagementService.Stub
        }
    }

    /**
     * Notify our observers of a route change.
     */
    private void notifyRouteChange(String action, RouteInfo route) {
        final int length = mObservers.beginBroadcast();
        try {
            for (int i = 0; i < length; i++) {
                try {
                    if (action.equals("updated")) {
                        mObservers.getBroadcastItem(i).routeUpdated(route);
                    } else {
                        mObservers.getBroadcastItem(i).routeRemoved(route);
                    }
                } catch (RemoteException e) {
                } catch (RuntimeException e) {
                }
            }
        } finally {
            mObservers.finishBroadcast();
        }
    }

    //
    // Netd Callback handling
    //
@@ -722,6 +746,47 @@ public class NetworkManagementService extends INetworkManagementService.Stub
                    }
                    return true;
                    // break;
            case NetdResponseCode.RouteChange:
                    /*
                     * A route has been updated or removed.
                     * Format: "NNN Route <updated|removed> <dst> [via <gateway] [dev <iface>]"
                     */
                    if (!cooked[1].equals("Route") || cooked.length < 6) {
                        throw new IllegalStateException(errorMessage);
                    }

                    String via = null;
                    String dev = null;
                    boolean valid = true;
                    for (int i = 4; (i + 1) < cooked.length && valid; i += 2) {
                        if (cooked[i].equals("dev")) {
                            if (dev == null) {
                                dev = cooked[i+1];
                            } else {
                                valid = false;  // Duplicate interface.
                            }
                        } else if (cooked[i].equals("via")) {
                            if (via == null) {
                                via = cooked[i+1];
                            } else {
                                valid = false;  // Duplicate gateway.
                            }
                        } else {
                            valid = false;      // Unknown syntax.
                        }
                    }
                    if (valid) {
                        try {
                            // InetAddress.parseNumericAddress(null) inexplicably returns ::1.
                            InetAddress gateway = null;
                            if (via != null) gateway = InetAddress.parseNumericAddress(via);
                            RouteInfo route = new RouteInfo(new IpPrefix(cooked[3]), gateway, dev);
                            notifyRouteChange(cooked[2], route);
                            return true;
                        } catch (IllegalArgumentException e) {}
                    }
                    throw new IllegalStateException(errorMessage);
                    // break;
            default: break;
            }
            return false;