OSDN Git Service

Make ConnectivityMetricsLogger and related classes @SystemApi
[android-x86/frameworks-base.git] / core / java / android / net / NetworkAgent.java
1 /*
2  * Copyright (C) 2014 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
17 package android.net;
18
19 import android.content.Context;
20 import android.os.Bundle;
21 import android.os.Handler;
22 import android.os.Looper;
23 import android.os.Message;
24 import android.os.Messenger;
25 import android.util.Log;
26
27 import com.android.internal.util.AsyncChannel;
28 import com.android.internal.util.Protocol;
29 import android.net.ConnectivityManager.PacketKeepalive;
30
31 import java.util.ArrayList;
32 import java.util.concurrent.atomic.AtomicBoolean;
33
34 /**
35  * A Utility class for handling for communicating between bearer-specific
36  * code and ConnectivityService.
37  *
38  * A bearer may have more than one NetworkAgent if it can simultaneously
39  * support separate networks (IMS / Internet / MMS Apns on cellular, or
40  * perhaps connections with different SSID or P2P for Wi-Fi).
41  *
42  * @hide
43  */
44 public abstract class NetworkAgent extends Handler {
45     // Guaranteed to be valid (not NETID_UNSET), otherwise registerNetworkAgent() would have thrown
46     // an exception.
47     public final int netId;
48
49     private volatile AsyncChannel mAsyncChannel;
50     private final String LOG_TAG;
51     private static final boolean DBG = true;
52     private static final boolean VDBG = false;
53     private final Context mContext;
54     private final ArrayList<Message>mPreConnectedQueue = new ArrayList<Message>();
55     private volatile long mLastBwRefreshTime = 0;
56     private static final long BW_REFRESH_MIN_WIN_MS = 500;
57     private boolean mPollLceScheduled = false;
58     private AtomicBoolean mPollLcePending = new AtomicBoolean(false);
59
60     private static final int BASE = Protocol.BASE_NETWORK_AGENT;
61
62     /**
63      * Sent by ConnectivityService to the NetworkAgent to inform it of
64      * suspected connectivity problems on its network.  The NetworkAgent
65      * should take steps to verify and correct connectivity.
66      */
67     public static final int CMD_SUSPECT_BAD = BASE;
68
69     /**
70      * Sent by the NetworkAgent (note the EVENT vs CMD prefix) to
71      * ConnectivityService to pass the current NetworkInfo (connection state).
72      * Sent when the NetworkInfo changes, mainly due to change of state.
73      * obj = NetworkInfo
74      */
75     public static final int EVENT_NETWORK_INFO_CHANGED = BASE + 1;
76
77     /**
78      * Sent by the NetworkAgent to ConnectivityService to pass the current
79      * NetworkCapabilties.
80      * obj = NetworkCapabilities
81      */
82     public static final int EVENT_NETWORK_CAPABILITIES_CHANGED = BASE + 2;
83
84     /**
85      * Sent by the NetworkAgent to ConnectivityService to pass the current
86      * NetworkProperties.
87      * obj = NetworkProperties
88      */
89     public static final int EVENT_NETWORK_PROPERTIES_CHANGED = BASE + 3;
90
91     /* centralize place where base network score, and network score scaling, will be
92      * stored, so as we can consistently compare apple and oranges, or wifi, ethernet and LTE
93      */
94     public static final int WIFI_BASE_SCORE = 60;
95
96     /**
97      * Sent by the NetworkAgent to ConnectivityService to pass the current
98      * network score.
99      * obj = network score Integer
100      */
101     public static final int EVENT_NETWORK_SCORE_CHANGED = BASE + 4;
102
103     /**
104      * Sent by the NetworkAgent to ConnectivityService to add new UID ranges
105      * to be forced into this Network.  For VPNs only.
106      * obj = UidRange[] to forward
107      */
108     public static final int EVENT_UID_RANGES_ADDED = BASE + 5;
109
110     /**
111      * Sent by the NetworkAgent to ConnectivityService to remove UID ranges
112      * from being forced into this Network.  For VPNs only.
113      * obj = UidRange[] to stop forwarding
114      */
115     public static final int EVENT_UID_RANGES_REMOVED = BASE + 6;
116
117     /**
118      * Sent by ConnectivityService to the NetworkAgent to inform the agent of the
119      * networks status - whether we could use the network or could not, due to
120      * either a bad network configuration (no internet link) or captive portal.
121      *
122      * arg1 = either {@code VALID_NETWORK} or {@code INVALID_NETWORK}
123      * obj = Bundle containing map from {@code REDIRECT_URL_KEY} to {@code String}
124      *       representing URL that Internet probe was redirect to, if it was redirected,
125      *       or mapping to {@code null} otherwise.
126      */
127     public static final int CMD_REPORT_NETWORK_STATUS = BASE + 7;
128
129     public static final int VALID_NETWORK = 1;
130     public static final int INVALID_NETWORK = 2;
131
132     public static String REDIRECT_URL_KEY = "redirect URL";
133
134      /**
135      * Sent by the NetworkAgent to ConnectivityService to indicate this network was
136      * explicitly selected.  This should be sent before the NetworkInfo is marked
137      * CONNECTED so it can be given special treatment at that time.
138      *
139      * obj = boolean indicating whether to use this network even if unvalidated
140      */
141     public static final int EVENT_SET_EXPLICITLY_SELECTED = BASE + 8;
142
143     /**
144      * Sent by ConnectivityService to the NetworkAgent to inform the agent of
145      * whether the network should in the future be used even if not validated.
146      * This decision is made by the user, but it is the network transport's
147      * responsibility to remember it.
148      *
149      * arg1 = 1 if true, 0 if false
150      */
151     public static final int CMD_SAVE_ACCEPT_UNVALIDATED = BASE + 9;
152
153     /**
154      * Sent by ConnectivityService to the NetworkAgent to inform the agent to pull
155      * the underlying network connection for updated bandwidth information.
156      */
157     public static final int CMD_REQUEST_BANDWIDTH_UPDATE = BASE + 10;
158
159     /**
160      * Sent by ConnectivityService to the NetworkAgent to request that the specified packet be sent
161      * periodically on the given interval.
162      *
163      *   arg1 = the slot number of the keepalive to start
164      *   arg2 = interval in seconds
165      *   obj = KeepalivePacketData object describing the data to be sent
166      *
167      * Also used internally by ConnectivityService / KeepaliveTracker, with different semantics.
168      */
169     public static final int CMD_START_PACKET_KEEPALIVE = BASE + 11;
170
171     /**
172      * Requests that the specified keepalive packet be stopped.
173      *
174      * arg1 = slot number of the keepalive to stop.
175      *
176      * Also used internally by ConnectivityService / KeepaliveTracker, with different semantics.
177      */
178     public static final int CMD_STOP_PACKET_KEEPALIVE = BASE + 12;
179
180     /**
181      * Sent by the NetworkAgent to ConnectivityService to provide status on a packet keepalive
182      * request. This may either be the reply to a CMD_START_PACKET_KEEPALIVE, or an asynchronous
183      * error notification.
184      *
185      * This is also sent by KeepaliveTracker to the app's ConnectivityManager.PacketKeepalive to
186      * so that the app's PacketKeepaliveCallback methods can be called.
187      *
188      * arg1 = slot number of the keepalive
189      * arg2 = error code
190      */
191     public static final int EVENT_PACKET_KEEPALIVE = BASE + 13;
192
193     /**
194      * Sent by ConnectivityService to inform this network transport of signal strength thresholds
195      * that when crossed should trigger a system wakeup and a NetworkCapabilities update.
196      *
197      *   obj = int[] describing signal strength thresholds.
198      */
199     public static final int CMD_SET_SIGNAL_STRENGTH_THRESHOLDS = BASE + 14;
200
201     /**
202      * Sent by ConnectivityService to the NeworkAgent to inform the agent to avoid
203      * automatically reconnecting to this network (e.g. via autojoin).  Happens
204      * when user selects "No" option on the "Stay connected?" dialog box.
205      */
206     public static final int CMD_PREVENT_AUTOMATIC_RECONNECT = BASE + 15;
207
208     public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni,
209             NetworkCapabilities nc, LinkProperties lp, int score) {
210         this(looper, context, logTag, ni, nc, lp, score, null);
211     }
212
213     public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni,
214             NetworkCapabilities nc, LinkProperties lp, int score, NetworkMisc misc) {
215         super(looper);
216         LOG_TAG = logTag;
217         mContext = context;
218         if (ni == null || nc == null || lp == null) {
219             throw new IllegalArgumentException();
220         }
221
222         if (VDBG) log("Registering NetworkAgent");
223         ConnectivityManager cm = (ConnectivityManager)mContext.getSystemService(
224                 Context.CONNECTIVITY_SERVICE);
225         netId = cm.registerNetworkAgent(new Messenger(this), new NetworkInfo(ni),
226                 new LinkProperties(lp), new NetworkCapabilities(nc), score, misc);
227     }
228
229     @Override
230     public void handleMessage(Message msg) {
231         switch (msg.what) {
232             case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: {
233                 if (mAsyncChannel != null) {
234                     log("Received new connection while already connected!");
235                 } else {
236                     if (VDBG) log("NetworkAgent fully connected");
237                     AsyncChannel ac = new AsyncChannel();
238                     ac.connected(null, this, msg.replyTo);
239                     ac.replyToMessage(msg, AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED,
240                             AsyncChannel.STATUS_SUCCESSFUL);
241                     synchronized (mPreConnectedQueue) {
242                         mAsyncChannel = ac;
243                         for (Message m : mPreConnectedQueue) {
244                             ac.sendMessage(m);
245                         }
246                         mPreConnectedQueue.clear();
247                     }
248                 }
249                 break;
250             }
251             case AsyncChannel.CMD_CHANNEL_DISCONNECT: {
252                 if (VDBG) log("CMD_CHANNEL_DISCONNECT");
253                 if (mAsyncChannel != null) mAsyncChannel.disconnect();
254                 break;
255             }
256             case AsyncChannel.CMD_CHANNEL_DISCONNECTED: {
257                 if (DBG) log("NetworkAgent channel lost");
258                 // let the client know CS is done with us.
259                 unwanted();
260                 synchronized (mPreConnectedQueue) {
261                     mAsyncChannel = null;
262                 }
263                 break;
264             }
265             case CMD_SUSPECT_BAD: {
266                 log("Unhandled Message " + msg);
267                 break;
268             }
269             case CMD_REQUEST_BANDWIDTH_UPDATE: {
270                 long currentTimeMs = System.currentTimeMillis();
271                 if (VDBG) {
272                     log("CMD_REQUEST_BANDWIDTH_UPDATE request received.");
273                 }
274                 if (currentTimeMs >= (mLastBwRefreshTime + BW_REFRESH_MIN_WIN_MS)) {
275                     mPollLceScheduled = false;
276                     if (mPollLcePending.getAndSet(true) == false) {
277                         pollLceData();
278                     }
279                 } else {
280                     // deliver the request at a later time rather than discard it completely.
281                     if (!mPollLceScheduled) {
282                         long waitTime = mLastBwRefreshTime + BW_REFRESH_MIN_WIN_MS -
283                                 currentTimeMs + 1;
284                         mPollLceScheduled = sendEmptyMessageDelayed(
285                                 CMD_REQUEST_BANDWIDTH_UPDATE, waitTime);
286                     }
287                 }
288                 break;
289             }
290             case CMD_REPORT_NETWORK_STATUS: {
291                 String redirectUrl = ((Bundle)msg.obj).getString(REDIRECT_URL_KEY);
292                 if (VDBG) {
293                     log("CMD_REPORT_NETWORK_STATUS(" +
294                             (msg.arg1 == VALID_NETWORK ? "VALID, " : "INVALID, ") + redirectUrl);
295                 }
296                 networkStatus(msg.arg1, redirectUrl);
297                 break;
298             }
299             case CMD_SAVE_ACCEPT_UNVALIDATED: {
300                 saveAcceptUnvalidated(msg.arg1 != 0);
301                 break;
302             }
303             case CMD_START_PACKET_KEEPALIVE: {
304                 startPacketKeepalive(msg);
305                 break;
306             }
307             case CMD_STOP_PACKET_KEEPALIVE: {
308                 stopPacketKeepalive(msg);
309                 break;
310             }
311
312             case CMD_SET_SIGNAL_STRENGTH_THRESHOLDS: {
313                 ArrayList<Integer> thresholds =
314                         ((Bundle) msg.obj).getIntegerArrayList("thresholds");
315                 // TODO: Change signal strength thresholds API to use an ArrayList<Integer>
316                 // rather than convert to int[].
317                 int[] intThresholds = new int[(thresholds != null) ? thresholds.size() : 0];
318                 for (int i = 0; i < intThresholds.length; i++) {
319                     intThresholds[i] = thresholds.get(i);
320                 }
321                 setSignalStrengthThresholds(intThresholds);
322                 break;
323             }
324             case CMD_PREVENT_AUTOMATIC_RECONNECT: {
325                 preventAutomaticReconnect();
326                 break;
327             }
328         }
329     }
330
331     private void queueOrSendMessage(int what, Object obj) {
332         queueOrSendMessage(what, 0, 0, obj);
333     }
334
335     private void queueOrSendMessage(int what, int arg1, int arg2) {
336         queueOrSendMessage(what, arg1, arg2, null);
337     }
338
339     private void queueOrSendMessage(int what, int arg1, int arg2, Object obj) {
340         Message msg = Message.obtain();
341         msg.what = what;
342         msg.arg1 = arg1;
343         msg.arg2 = arg2;
344         msg.obj = obj;
345         queueOrSendMessage(msg);
346     }
347
348     private void queueOrSendMessage(Message msg) {
349         synchronized (mPreConnectedQueue) {
350             if (mAsyncChannel != null) {
351                 mAsyncChannel.sendMessage(msg);
352             } else {
353                 mPreConnectedQueue.add(msg);
354             }
355         }
356     }
357
358     /**
359      * Called by the bearer code when it has new LinkProperties data.
360      */
361     public void sendLinkProperties(LinkProperties linkProperties) {
362         queueOrSendMessage(EVENT_NETWORK_PROPERTIES_CHANGED, new LinkProperties(linkProperties));
363     }
364
365     /**
366      * Called by the bearer code when it has new NetworkInfo data.
367      */
368     public void sendNetworkInfo(NetworkInfo networkInfo) {
369         queueOrSendMessage(EVENT_NETWORK_INFO_CHANGED, new NetworkInfo(networkInfo));
370     }
371
372     /**
373      * Called by the bearer code when it has new NetworkCapabilities data.
374      */
375     public void sendNetworkCapabilities(NetworkCapabilities networkCapabilities) {
376         mPollLcePending.set(false);
377         mLastBwRefreshTime = System.currentTimeMillis();
378         queueOrSendMessage(EVENT_NETWORK_CAPABILITIES_CHANGED,
379                 new NetworkCapabilities(networkCapabilities));
380     }
381
382     /**
383      * Called by the bearer code when it has a new score for this network.
384      */
385     public void sendNetworkScore(int score) {
386         if (score < 0) {
387             throw new IllegalArgumentException("Score must be >= 0");
388         }
389         queueOrSendMessage(EVENT_NETWORK_SCORE_CHANGED, new Integer(score));
390     }
391
392     /**
393      * Called by the VPN code when it wants to add ranges of UIDs to be routed
394      * through the VPN network.
395      */
396     public void addUidRanges(UidRange[] ranges) {
397         queueOrSendMessage(EVENT_UID_RANGES_ADDED, ranges);
398     }
399
400     /**
401      * Called by the VPN code when it wants to remove ranges of UIDs from being routed
402      * through the VPN network.
403      */
404     public void removeUidRanges(UidRange[] ranges) {
405         queueOrSendMessage(EVENT_UID_RANGES_REMOVED, ranges);
406     }
407
408     /**
409      * Called by the bearer to indicate this network was manually selected by the user.
410      * This should be called before the NetworkInfo is marked CONNECTED so that this
411      * Network can be given special treatment at that time. If {@code acceptUnvalidated} is
412      * {@code true}, then the system will switch to this network. If it is {@code false} and the
413      * network cannot be validated, the system will ask the user whether to switch to this network.
414      * If the user confirms and selects "don't ask again", then the system will call
415      * {@link #saveAcceptUnvalidated} to persist the user's choice. Thus, if the transport ever
416      * calls this method with {@code acceptUnvalidated} set to {@code false}, it must also implement
417      * {@link #saveAcceptUnvalidated} to respect the user's choice.
418      */
419     public void explicitlySelected(boolean acceptUnvalidated) {
420         queueOrSendMessage(EVENT_SET_EXPLICITLY_SELECTED, acceptUnvalidated);
421     }
422
423     /**
424      * Called when ConnectivityService has indicated they no longer want this network.
425      * The parent factory should (previously) have received indication of the change
426      * as well, either canceling NetworkRequests or altering their score such that this
427      * network won't be immediately requested again.
428      */
429     abstract protected void unwanted();
430
431     /**
432      * Called when ConnectivityService request a bandwidth update. The parent factory
433      * shall try to overwrite this method and produce a bandwidth update if capable.
434      */
435     protected void pollLceData() {
436     }
437
438     /**
439      * Called when the system determines the usefulness of this network.
440      *
441      * Networks claiming internet connectivity will have their internet
442      * connectivity verified.
443      *
444      * Currently there are two possible values:
445      * {@code VALID_NETWORK} if the system is happy with the connection,
446      * {@code INVALID_NETWORK} if the system is not happy.
447      * TODO - add indications of captive portal-ness and related success/failure,
448      * ie, CAPTIVE_SUCCESS_NETWORK, CAPTIVE_NETWORK for successful login and detection
449      *
450      * This may be called multiple times as the network status changes and may
451      * generate false negatives if we lose ip connectivity before the link is torn down.
452      *
453      * @param status one of {@code VALID_NETWORK} or {@code INVALID_NETWORK}.
454      * @param redirectUrl If the Internet probe was redirected, this is the destination it was
455      *         redirected to, otherwise {@code null}.
456      */
457     protected void networkStatus(int status, String redirectUrl) {
458     }
459
460     /**
461      * Called when the user asks to remember the choice to use this network even if unvalidated.
462      * The transport is responsible for remembering the choice, and the next time the user connects
463      * to the network, should explicitlySelected with {@code acceptUnvalidated} set to {@code true}.
464      * This method will only be called if {@link #explicitlySelected} was called with
465      * {@code acceptUnvalidated} set to {@code false}.
466      */
467     protected void saveAcceptUnvalidated(boolean accept) {
468     }
469
470     /**
471      * Requests that the network hardware send the specified packet at the specified interval.
472      */
473     protected void startPacketKeepalive(Message msg) {
474         onPacketKeepaliveEvent(msg.arg1, PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
475     }
476
477     /**
478      * Requests that the network hardware send the specified packet at the specified interval.
479      */
480     protected void stopPacketKeepalive(Message msg) {
481         onPacketKeepaliveEvent(msg.arg1, PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
482     }
483
484     /**
485      * Called by the network when a packet keepalive event occurs.
486      */
487     public void onPacketKeepaliveEvent(int slot, int reason) {
488         queueOrSendMessage(EVENT_PACKET_KEEPALIVE, slot, reason);
489     }
490
491     /**
492      * Called by ConnectivityService to inform this network transport of signal strength thresholds
493      * that when crossed should trigger a system wakeup and a NetworkCapabilities update.
494      */
495     protected void setSignalStrengthThresholds(int[] thresholds) {
496     }
497
498     /**
499      * Called when the user asks to not stay connected to this network because it was found to not
500      * provide Internet access.  Usually followed by call to {@code unwanted}.  The transport is
501      * responsible for making sure the device does not automatically reconnect to the same network
502      * after the {@code unwanted} call.
503      */
504     protected void preventAutomaticReconnect() {
505     }
506
507     protected void log(String s) {
508         Log.d(LOG_TAG, "NetworkAgent: " + s);
509     }
510 }