NetworkAgent.java revision 49f63fbed4cd84f5da182c85e8b999037dc64f3b
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
17package android.net;
18
19import android.content.Context;
20import android.os.Handler;
21import android.os.Looper;
22import android.os.Message;
23import android.os.Messenger;
24import android.os.Parcel;
25import android.os.Parcelable;
26import android.util.Log;
27
28import com.android.internal.util.AsyncChannel;
29import com.android.internal.util.Protocol;
30
31import java.util.ArrayList;
32import 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 */
44public abstract class NetworkAgent extends Handler {
45    private volatile AsyncChannel mAsyncChannel;
46    private final String LOG_TAG;
47    private static final boolean DBG = true;
48    private static final boolean VDBG = false;
49    private final Context mContext;
50    private final ArrayList<Message>mPreConnectedQueue = new ArrayList<Message>();
51
52    private static final int BASE = Protocol.BASE_NETWORK_AGENT;
53
54    /**
55     * Sent by ConnectivityService to the NetworkAgent to inform it of
56     * suspected connectivity problems on its network.  The NetworkAgent
57     * should take steps to verify and correct connectivity.
58     */
59    public static final int CMD_SUSPECT_BAD = BASE;
60
61    /**
62     * Sent by the NetworkAgent (note the EVENT vs CMD prefix) to
63     * ConnectivityService to pass the current NetworkInfo (connection state).
64     * Sent when the NetworkInfo changes, mainly due to change of state.
65     * obj = NetworkInfo
66     */
67    public static final int EVENT_NETWORK_INFO_CHANGED = BASE + 1;
68
69    /**
70     * Sent by the NetworkAgent to ConnectivityService to pass the current
71     * NetworkCapabilties.
72     * obj = NetworkCapabilities
73     */
74    public static final int EVENT_NETWORK_CAPABILITIES_CHANGED = BASE + 2;
75
76    /**
77     * Sent by the NetworkAgent to ConnectivityService to pass the current
78     * NetworkProperties.
79     * obj = NetworkProperties
80     */
81    public static final int EVENT_NETWORK_PROPERTIES_CHANGED = BASE + 3;
82
83    /* centralize place where base network score, and network score scaling, will be
84     * stored, so as we can consistently compare apple and oranges, or wifi, ethernet and LTE
85     */
86    public static final int WIFI_BASE_SCORE = 60;
87
88    /**
89     * Sent by the NetworkAgent to ConnectivityService to pass the current
90     * network score.
91     * obj = network score Integer
92     */
93    public static final int EVENT_NETWORK_SCORE_CHANGED = BASE + 4;
94
95    /**
96     * Sent by the NetworkAgent to ConnectivityService to add new UID ranges
97     * to be forced into this Network.  For VPNs only.
98     * obj = UidRange[] to forward
99     */
100    public static final int EVENT_UID_RANGES_ADDED = BASE + 5;
101
102    /**
103     * Sent by the NetworkAgent to ConnectivityService to remove UID ranges
104     * from being forced into this Network.  For VPNs only.
105     * obj = UidRange[] to stop forwarding
106     */
107    public static final int EVENT_UID_RANGES_REMOVED = BASE + 6;
108
109    /**
110     * Sent by the NetworkAgent to ConnectivityService to block all routes for a certain address
111     * family (AF_INET or AF_INET6) on this Network. For VPNs only.
112     * obj = Integer representing the family (AF_INET or AF_INET6)
113     */
114    public static final int EVENT_BLOCK_ADDRESS_FAMILY = BASE + 7;
115
116    /**
117     * Sent by the NetworkAgent to ConnectivityService to unblock routes for a certain address
118     * family (AF_INET or AF_INET6) on this Network. For VPNs only.
119     * obj = Integer representing the family (AF_INET or AF_INET6)
120     */
121    public static final int EVENT_UNBLOCK_ADDRESS_FAMILY = BASE + 8;
122
123    /**
124     * Sent by ConnectivitySerice to the NetworkAgent to inform the agent of the
125     * networks status - whether we could use the network or could not, due to
126     * either a bad network configuration (no internet link) or captive portal.
127     *
128     * arg1 = either {@code VALID_NETWORK} or {@code INVALID_NETWORK}
129     */
130    public static final int CMD_REPORT_NETWORK_STATUS = BASE + 9;
131
132    public static final int VALID_NETWORK = 1;
133    public static final int INVALID_NETWORK = 2;
134
135    public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni,
136            NetworkCapabilities nc, LinkProperties lp, int score) {
137        this(looper, context, logTag, ni, nc, lp, score, null);
138    }
139
140    public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni,
141            NetworkCapabilities nc, LinkProperties lp, int score, NetworkMisc misc) {
142        super(looper);
143        LOG_TAG = logTag;
144        mContext = context;
145        if (ni == null || nc == null || lp == null) {
146            throw new IllegalArgumentException();
147        }
148
149        if (VDBG) log("Registering NetworkAgent");
150        ConnectivityManager cm = (ConnectivityManager)mContext.getSystemService(
151                Context.CONNECTIVITY_SERVICE);
152        cm.registerNetworkAgent(new Messenger(this), new NetworkInfo(ni),
153                new LinkProperties(lp), new NetworkCapabilities(nc), score, misc);
154    }
155
156    @Override
157    public void handleMessage(Message msg) {
158        switch (msg.what) {
159            case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: {
160                if (mAsyncChannel != null) {
161                    log("Received new connection while already connected!");
162                } else {
163                    if (VDBG) log("NetworkAgent fully connected");
164                    AsyncChannel ac = new AsyncChannel();
165                    ac.connected(null, this, msg.replyTo);
166                    ac.replyToMessage(msg, AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED,
167                            AsyncChannel.STATUS_SUCCESSFUL);
168                    synchronized (mPreConnectedQueue) {
169                        mAsyncChannel = ac;
170                        for (Message m : mPreConnectedQueue) {
171                            ac.sendMessage(m);
172                        }
173                        mPreConnectedQueue.clear();
174                    }
175                }
176                break;
177            }
178            case AsyncChannel.CMD_CHANNEL_DISCONNECT: {
179                if (VDBG) log("CMD_CHANNEL_DISCONNECT");
180                if (mAsyncChannel != null) mAsyncChannel.disconnect();
181                break;
182            }
183            case AsyncChannel.CMD_CHANNEL_DISCONNECTED: {
184                if (DBG) log("NetworkAgent channel lost");
185                // let the client know CS is done with us.
186                unwanted();
187                synchronized (mPreConnectedQueue) {
188                    mAsyncChannel = null;
189                }
190                break;
191            }
192            case CMD_SUSPECT_BAD: {
193                log("Unhandled Message " + msg);
194                break;
195            }
196            case CMD_REPORT_NETWORK_STATUS: {
197                if (VDBG) {
198                    log("CMD_REPORT_NETWORK_STATUS(" +
199                            (msg.arg1 == VALID_NETWORK ? "VALID)" : "INVALID)"));
200                }
201                networkStatus(msg.arg1);
202                break;
203            }
204        }
205    }
206
207    private void queueOrSendMessage(int what, Object obj) {
208        synchronized (mPreConnectedQueue) {
209            if (mAsyncChannel != null) {
210                mAsyncChannel.sendMessage(what, obj);
211            } else {
212                Message msg = Message.obtain();
213                msg.what = what;
214                msg.obj = obj;
215                mPreConnectedQueue.add(msg);
216            }
217        }
218    }
219
220    /**
221     * Called by the bearer code when it has new LinkProperties data.
222     */
223    public void sendLinkProperties(LinkProperties linkProperties) {
224        queueOrSendMessage(EVENT_NETWORK_PROPERTIES_CHANGED, new LinkProperties(linkProperties));
225    }
226
227    /**
228     * Called by the bearer code when it has new NetworkInfo data.
229     */
230    public void sendNetworkInfo(NetworkInfo networkInfo) {
231        queueOrSendMessage(EVENT_NETWORK_INFO_CHANGED, new NetworkInfo(networkInfo));
232    }
233
234    /**
235     * Called by the bearer code when it has new NetworkCapabilities data.
236     */
237    public void sendNetworkCapabilities(NetworkCapabilities networkCapabilities) {
238        queueOrSendMessage(EVENT_NETWORK_CAPABILITIES_CHANGED,
239                new NetworkCapabilities(networkCapabilities));
240    }
241
242    /**
243     * Called by the bearer code when it has a new score for this network.
244     */
245    public void sendNetworkScore(int score) {
246        if (score < 0) {
247            throw new IllegalArgumentException("Score must be >= 0");
248        }
249        queueOrSendMessage(EVENT_NETWORK_SCORE_CHANGED, new Integer(score));
250    }
251
252    /**
253     * Called by the VPN code when it wants to add ranges of UIDs to be routed
254     * through the VPN network.
255     */
256    public void addUidRanges(UidRange[] ranges) {
257        queueOrSendMessage(EVENT_UID_RANGES_ADDED, ranges);
258    }
259
260    /**
261     * Called by the VPN code when it wants to remove ranges of UIDs from being routed
262     * through the VPN network.
263     */
264    public void removeUidRanges(UidRange[] ranges) {
265        queueOrSendMessage(EVENT_UID_RANGES_REMOVED, ranges);
266    }
267
268    /**
269     * Called by the VPN code when it wants to block an address family from being routed, typically
270     * because the VPN network doesn't support that family.
271     */
272    public void blockAddressFamily(int family) {
273        queueOrSendMessage(EVENT_BLOCK_ADDRESS_FAMILY, family);
274    }
275
276    /**
277     * Called by the VPN code when it wants to unblock an address family from being routed.
278     */
279    public void unblockAddressFamily(int family) {
280        queueOrSendMessage(EVENT_UNBLOCK_ADDRESS_FAMILY, family);
281    }
282
283    /**
284     * Called when ConnectivityService has indicated they no longer want this network.
285     * The parent factory should (previously) have received indication of the change
286     * as well, either canceling NetworkRequests or altering their score such that this
287     * network won't be immediately requested again.
288     */
289    abstract protected void unwanted();
290
291    /**
292     * Called when the system determines the usefulness of this network.
293     *
294     * Networks claiming internet connectivity will have their internet
295     * connectivity verified.
296     *
297     * Currently there are two possible values:
298     * {@code VALID_NETWORK} if the system is happy with the connection,
299     * {@code INVALID_NETWORK} if the system is not happy.
300     * TODO - add indications of captive portal-ness and related success/failure,
301     * ie, CAPTIVE_SUCCESS_NETWORK, CAPTIVE_NETWORK for successful login and detection
302     *
303     * This may be called multiple times as the network status changes and may
304     * generate false negatives if we lose ip connectivity before the link is torn down.
305     */
306    protected void networkStatus(int status) {
307    }
308
309    protected void log(String s) {
310        Log.d(LOG_TAG, "NetworkAgent: " + s);
311    }
312}
313