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

Commit ca349caa authored by Remi NGUYEN VAN's avatar Remi NGUYEN VAN Committed by android-build-merger
Browse files

Merge "Add NetworkObserverRegistry to NetworkStack" am: 375b3c07 am: 9a481041

am: ecac3d1b

Change-Id: I63c258d07eccb61889bcb37b3a8819e80a42c692
parents 88938aae ecac3d1b
Loading
Loading
Loading
Loading
+87 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server;

import android.net.LinkAddress;

/**
 * Observer for network events, to use with {@link NetworkObserverRegistry}.
 */
public interface NetworkObserver {

    /**
     * @see android.net.INetdUnsolicitedEventListener#onInterfaceChanged(java.lang.String, boolean)
     */
    default void onInterfaceChanged(String ifName, boolean up) {}

    /**
     * @see android.net.INetdUnsolicitedEventListener#onInterfaceRemoved(String)
     */
    default void onInterfaceRemoved(String ifName) {}

    /**
     * @see android.net.INetdUnsolicitedEventListener
     *          #onInterfaceAddressUpdated(String, String, int, int)
     */
    default void onInterfaceAddressUpdated(LinkAddress address, String ifName) {}

    /**
     * @see android.net.INetdUnsolicitedEventListener
     *          #onInterfaceAddressRemoved(String, String, int, int)
     */
    default void onInterfaceAddressRemoved(LinkAddress address, String ifName) {}

    /**
     * @see android.net.INetdUnsolicitedEventListener#onInterfaceLinkStateChanged(String, boolean)
     */
    default void onInterfaceLinkStateChanged(String ifName, boolean up) {}

    /**
     * @see android.net.INetdUnsolicitedEventListener#onInterfaceAdded(String)
     */
    default void onInterfaceAdded(String ifName) {}

    /**
     * @see android.net.INetdUnsolicitedEventListener
     *          #onInterfaceClassActivityChanged(boolean, int, long, int)
     */
    default void onInterfaceClassActivityChanged(
            boolean isActive, int label, long timestamp, int uid) {}

    /**
     * @see android.net.INetdUnsolicitedEventListener#onQuotaLimitReached(String, String)
     */
    default void onQuotaLimitReached(String alertName, String ifName) {}

    /**
     * @see android.net.INetdUnsolicitedEventListener
     *          #onInterfaceDnsServerInfo(String, long, String[])
     */
    default void onInterfaceDnsServerInfo(String ifName, long lifetime, String[] servers) {}

    /**
     * @see android.net.INetdUnsolicitedEventListener
     *          #onRouteChanged(boolean, String, String, String)
     */
    default void onRouteUpdated(String route, String gateway, String ifName) {}

    /**
     * @see android.net.INetdUnsolicitedEventListener
     *          #onRouteChanged(boolean, String, String, String)
     */
    default void onRouteRemoved(String route, String gateway, String ifName) {}
}
+150 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.android.server;

import android.annotation.NonNull;
import android.net.INetd;
import android.net.INetdUnsolicitedEventListener;
import android.net.LinkAddress;
import android.os.Handler;
import android.os.RemoteException;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * A class for reporting network events to clients.
 *
 * Implements INetdUnsolicitedEventListener and registers with netd, and relays those events to
 * all INetworkManagementEventObserver objects that have registered with it.
 */
public class NetworkObserverRegistry extends INetdUnsolicitedEventListener.Stub {

    /**
     * Constructs a new NetworkObserverRegistry.
     *
     * <p>Only one registry should be used per process since netd will silently ignore multiple
     * registrations from the same process.
     */
    NetworkObserverRegistry() {}

    /**
     * Start listening for Netd events.
     *
     * <p>This should be called before allowing any observer to be registered.
     */
    void register(@NonNull INetd netd) throws RemoteException {
        netd.registerUnsolicitedEventListener(this);
    }

    private final ConcurrentHashMap<NetworkObserver, Handler> mObservers =
            new ConcurrentHashMap<>();

    /**
     * Registers the specified observer and start sending callbacks to it.
     * This method may be called on any thread.
     */
    public void registerObserver(@NonNull NetworkObserver observer, @NonNull Handler handler) {
        mObservers.put(observer, handler);
    }

    /**
     * Unregisters the specified observer and stop sending callbacks to it.
     * This method may be called on any thread.
     */
    public void unregisterObserver(@NonNull NetworkObserver observer) {
        mObservers.remove(observer);
    }

    @FunctionalInterface
    private interface NetworkObserverEventCallback {
        void sendCallback(NetworkObserver o);
    }

    private void invokeForAllObservers(@NonNull final NetworkObserverEventCallback callback) {
        // ConcurrentHashMap#entrySet is weakly consistent: observers that were in the map before
        // creation will be processed, those added during traversal may or may not.
        for (Map.Entry<NetworkObserver, Handler> entry : mObservers.entrySet()) {
            final NetworkObserver observer = entry.getKey();
            entry.getValue().post(() -> callback.sendCallback(observer));
        }
    }

    @Override
    public void onInterfaceClassActivityChanged(boolean isActive,
            int label, long timestamp, int uid) {
        invokeForAllObservers(o -> o.onInterfaceClassActivityChanged(
                isActive, label, timestamp, uid));
    }

    /**
     * Notify our observers of a limit reached.
     */
    @Override
    public void onQuotaLimitReached(String alertName, String ifName) {
        invokeForAllObservers(o -> o.onQuotaLimitReached(alertName, ifName));
    }

    @Override
    public void onInterfaceDnsServerInfo(String ifName, long lifetime, String[] servers) {
        invokeForAllObservers(o -> o.onInterfaceDnsServerInfo(ifName, lifetime, servers));
    }

    @Override
    public void onInterfaceAddressUpdated(String addr, String ifName, int flags, int scope) {
        final LinkAddress address = new LinkAddress(addr, flags, scope);
        invokeForAllObservers(o -> o.onInterfaceAddressUpdated(address, ifName));
    }

    @Override
    public void onInterfaceAddressRemoved(String addr,
            String ifName, int flags, int scope) {
        final LinkAddress address = new LinkAddress(addr, flags, scope);
        invokeForAllObservers(o -> o.onInterfaceAddressRemoved(address, ifName));
    }

    @Override
    public void onInterfaceAdded(String ifName) {
        invokeForAllObservers(o -> o.onInterfaceAdded(ifName));
    }

    @Override
    public void onInterfaceRemoved(String ifName) {
        invokeForAllObservers(o -> o.onInterfaceRemoved(ifName));
    }

    @Override
    public void onInterfaceChanged(String ifName, boolean up) {
        invokeForAllObservers(o -> o.onInterfaceChanged(ifName, up));
    }

    @Override
    public void onInterfaceLinkStateChanged(String ifName, boolean up) {
        invokeForAllObservers(o -> o.onInterfaceLinkStateChanged(ifName, up));
    }

    @Override
    public void onRouteChanged(boolean updated, String route, String gateway, String ifName) {
        if (updated) {
            invokeForAllObservers(o -> o.onRouteUpdated(route, gateway, ifName));
        } else {
            invokeForAllObservers(o -> o.onRouteRemoved(route, gateway, ifName));
        }
    }

    @Override
    public void onStrictCleartextDetected(int uid, String hex) {}
}
+13 −2
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.INetd;
import android.net.INetworkMonitor;
import android.net.INetworkMonitorCallbacks;
import android.net.INetworkStackConnector;
@@ -65,6 +66,7 @@ import java.util.Iterator;
 */
public class NetworkStackService extends Service {
    private static final String TAG = NetworkStackService.class.getSimpleName();
    private static NetworkStackConnector sConnector;

    /**
     * Create a binder connector for the system server to communicate with the network stack.
@@ -72,8 +74,11 @@ public class NetworkStackService extends Service {
     * <p>On platforms where the network stack runs in the system server process, this method may
     * be called directly instead of obtaining the connector by binding to the service.
     */
    public static IBinder makeConnector(Context context) {
        return new NetworkStackConnector(context);
    public static synchronized IBinder makeConnector(Context context) {
        if (sConnector == null) {
            sConnector = new NetworkStackConnector(context);
        }
        return sConnector;
    }

    @NonNull
@@ -85,6 +90,8 @@ public class NetworkStackService extends Service {
    private static class NetworkStackConnector extends INetworkStackConnector.Stub {
        private static final int NUM_VALIDATION_LOG_LINES = 20;
        private final Context mContext;
        private final INetd mNetd;
        private final NetworkObserverRegistry mObserverRegistry;
        private final ConnectivityManager mCm;
        @GuardedBy("mIpClients")
        private final ArrayList<WeakReference<IpClient>> mIpClients = new ArrayList<>();
@@ -106,7 +113,11 @@ public class NetworkStackService extends Service {

        NetworkStackConnector(Context context) {
            mContext = context;
            mNetd = (INetd) context.getSystemService(Context.NETD_SERVICE);
            mObserverRegistry = new NetworkObserverRegistry();
            mCm = context.getSystemService(ConnectivityManager.class);

            // TODO: call mObserverRegistry here after adding sepolicy changes
        }

        @NonNull