Loading packages/NetworkStack/src/com/android/server/NetworkObserver.java 0 → 100644 +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) {} } packages/NetworkStack/src/com/android/server/NetworkObserverRegistry.java 0 → 100644 +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) {} } packages/NetworkStack/src/com/android/server/NetworkStackService.java +13 −2 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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. Loading @@ -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 Loading @@ -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<>(); Loading @@ -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 Loading Loading
packages/NetworkStack/src/com/android/server/NetworkObserver.java 0 → 100644 +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) {} }
packages/NetworkStack/src/com/android/server/NetworkObserverRegistry.java 0 → 100644 +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) {} }
packages/NetworkStack/src/com/android/server/NetworkStackService.java +13 −2 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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. Loading @@ -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 Loading @@ -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<>(); Loading @@ -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 Loading