• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.android.server;
17 
18 import static android.net.RouteInfo.RTN_UNICAST;
19 
20 import android.annotation.NonNull;
21 import android.net.INetd;
22 import android.net.INetdUnsolicitedEventListener;
23 import android.net.InetAddresses;
24 import android.net.IpPrefix;
25 import android.net.LinkAddress;
26 import android.net.RouteInfo;
27 import android.os.Handler;
28 import android.os.RemoteException;
29 import android.util.Log;
30 
31 import java.util.Map;
32 import java.util.Optional;
33 import java.util.concurrent.ConcurrentHashMap;
34 
35 /**
36  * A class for reporting network events to clients.
37  *
38  * Implements INetdUnsolicitedEventListener and registers with netd, and relays those events to
39  * all INetworkManagementEventObserver objects that have registered with it.
40  */
41 public class NetworkObserverRegistry extends INetdUnsolicitedEventListener.Stub {
42     private static final String TAG = NetworkObserverRegistry.class.getSimpleName();
43 
44     /**
45      * Constructs a new NetworkObserverRegistry.
46      *
47      * <p>Only one registry should be used per process since netd will silently ignore multiple
48      * registrations from the same process.
49      */
NetworkObserverRegistry()50     NetworkObserverRegistry() {}
51 
52     /**
53      * Start listening for Netd events.
54      *
55      * <p>This should be called before allowing any observer to be registered.
56      */
register(@onNull INetd netd)57     void register(@NonNull INetd netd) throws RemoteException {
58         netd.registerUnsolicitedEventListener(this);
59     }
60 
61     private final ConcurrentHashMap<NetworkObserver, Optional<Handler>> mObservers =
62             new ConcurrentHashMap<>();
63 
64     /**
65      * Registers the specified observer and start sending callbacks to it.
66      * This method may be called on any thread.
67      */
registerObserver(@onNull NetworkObserver observer, @NonNull Handler handler)68     public void registerObserver(@NonNull NetworkObserver observer, @NonNull Handler handler) {
69         if (handler == null) {
70             throw new IllegalArgumentException("handler must be non-null");
71         }
72         mObservers.put(observer, Optional.of(handler));
73     }
74 
75     /**
76      * Registers the specified observer, and start sending callbacks to it.
77      *
78      * <p>This method must only be called with callbacks that are nonblocking, such as callbacks
79      * that only send a message to a StateMachine.
80      */
registerObserverForNonblockingCallback(@onNull NetworkObserver observer)81     public void registerObserverForNonblockingCallback(@NonNull NetworkObserver observer) {
82         mObservers.put(observer, Optional.empty());
83     }
84 
85     /**
86      * Unregisters the specified observer and stop sending callbacks to it.
87      * This method may be called on any thread.
88      */
unregisterObserver(@onNull NetworkObserver observer)89     public void unregisterObserver(@NonNull NetworkObserver observer) {
90         mObservers.remove(observer);
91     }
92 
93     @FunctionalInterface
94     private interface NetworkObserverEventCallback {
sendCallback(NetworkObserver o)95         void sendCallback(NetworkObserver o);
96     }
97 
invokeForAllObservers(@onNull final NetworkObserverEventCallback callback)98     private void invokeForAllObservers(@NonNull final NetworkObserverEventCallback callback) {
99         // ConcurrentHashMap#entrySet is weakly consistent: observers that were in the map before
100         // creation will be processed, those added during traversal may or may not.
101         for (Map.Entry<NetworkObserver, Optional<Handler>> entry : mObservers.entrySet()) {
102             final NetworkObserver observer = entry.getKey();
103             final Optional<Handler> handler = entry.getValue();
104             if (handler.isPresent()) {
105                 handler.get().post(() -> callback.sendCallback(observer));
106                 return;
107             }
108 
109             try {
110                 callback.sendCallback(observer);
111             } catch (RuntimeException e) {
112                 Log.e(TAG, "Error sending callback to observer", e);
113             }
114         }
115     }
116 
117     @Override
onInterfaceClassActivityChanged(boolean isActive, int label, long timestamp, int uid)118     public void onInterfaceClassActivityChanged(boolean isActive,
119             int label, long timestamp, int uid) {
120         invokeForAllObservers(o -> o.onInterfaceClassActivityChanged(
121                 isActive, label, timestamp, uid));
122     }
123 
124     /**
125      * Notify our observers of a limit reached.
126      */
127     @Override
onQuotaLimitReached(String alertName, String ifName)128     public void onQuotaLimitReached(String alertName, String ifName) {
129         invokeForAllObservers(o -> o.onQuotaLimitReached(alertName, ifName));
130     }
131 
132     @Override
onInterfaceDnsServerInfo(String ifName, long lifetime, String[] servers)133     public void onInterfaceDnsServerInfo(String ifName, long lifetime, String[] servers) {
134         invokeForAllObservers(o -> o.onInterfaceDnsServerInfo(ifName, lifetime, servers));
135     }
136 
137     @Override
onInterfaceAddressUpdated(String addr, String ifName, int flags, int scope)138     public void onInterfaceAddressUpdated(String addr, String ifName, int flags, int scope) {
139         final LinkAddress address = new LinkAddress(addr, flags, scope);
140         invokeForAllObservers(o -> o.onInterfaceAddressUpdated(address, ifName));
141     }
142 
143     @Override
onInterfaceAddressRemoved(String addr, String ifName, int flags, int scope)144     public void onInterfaceAddressRemoved(String addr,
145             String ifName, int flags, int scope) {
146         final LinkAddress address = new LinkAddress(addr, flags, scope);
147         invokeForAllObservers(o -> o.onInterfaceAddressRemoved(address, ifName));
148     }
149 
150     @Override
onInterfaceAdded(String ifName)151     public void onInterfaceAdded(String ifName) {
152         invokeForAllObservers(o -> o.onInterfaceAdded(ifName));
153     }
154 
155     @Override
onInterfaceRemoved(String ifName)156     public void onInterfaceRemoved(String ifName) {
157         invokeForAllObservers(o -> o.onInterfaceRemoved(ifName));
158     }
159 
160     @Override
onInterfaceChanged(String ifName, boolean up)161     public void onInterfaceChanged(String ifName, boolean up) {
162         invokeForAllObservers(o -> o.onInterfaceChanged(ifName, up));
163     }
164 
165     @Override
onInterfaceLinkStateChanged(String ifName, boolean up)166     public void onInterfaceLinkStateChanged(String ifName, boolean up) {
167         invokeForAllObservers(o -> o.onInterfaceLinkStateChanged(ifName, up));
168     }
169 
170     @Override
onRouteChanged(boolean updated, String route, String gateway, String ifName)171     public void onRouteChanged(boolean updated, String route, String gateway, String ifName) {
172         final RouteInfo processRoute = new RouteInfo(new IpPrefix(route),
173                 ("".equals(gateway)) ? null : InetAddresses.parseNumericAddress(gateway),
174                 ifName, RTN_UNICAST);
175         if (updated) {
176             invokeForAllObservers(o -> o.onRouteUpdated(processRoute));
177         } else {
178             invokeForAllObservers(o -> o.onRouteRemoved(processRoute));
179         }
180     }
181 
182     @Override
onStrictCleartextDetected(int uid, String hex)183     public void onStrictCleartextDetected(int uid, String hex) {}
184 
185     @Override
getInterfaceVersion()186     public int getInterfaceVersion() {
187         return INetdUnsolicitedEventListener.VERSION;
188     }
189 }
190