blob: cab88b9972b5e4d2172ca28f8a141dd6f6e559a7 [file] [log] [blame]
Robert Greenwalt3192dec2014-05-27 13:20:24 -07001/*
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;
Robert Greenwalt3192dec2014-05-27 13:20:24 -070024import android.util.Log;
25import android.util.SparseArray;
26
Robert Greenwalt348e98d2015-06-05 17:55:36 -070027import com.android.internal.annotations.VisibleForTesting;
Robert Greenwalt3d68dee2015-06-10 20:25:14 -070028import com.android.internal.util.IndentingPrintWriter;
Robert Greenwalt3192dec2014-05-27 13:20:24 -070029import com.android.internal.util.Protocol;
30
Robert Greenwalt3d68dee2015-06-10 20:25:14 -070031import java.io.FileDescriptor;
32import java.io.PrintWriter;
33
Robert Greenwalt3192dec2014-05-27 13:20:24 -070034/**
35 * A NetworkFactory is an entity that creates NetworkAgent objects.
36 * The bearers register with ConnectivityService using {@link #register} and
37 * their factory will start receiving scored NetworkRequests. NetworkRequests
38 * can be filtered 3 ways: by NetworkCapabilities, by score and more complexly by
39 * overridden function. All of these can be dynamic - changing NetworkCapabilities
40 * or score forces re-evaluation of all current requests.
41 *
42 * If any requests pass the filter some overrideable functions will be called.
43 * If the bearer only cares about very simple start/stopNetwork callbacks, those
44 * functions can be overridden. If the bearer needs more interaction, it can
45 * override addNetworkRequest and removeNetworkRequest which will give it each
46 * request that passes their current filters.
47 * @hide
48 **/
49public class NetworkFactory extends Handler {
50 private static final boolean DBG = true;
Robert Greenwaltfc0c6892014-08-27 14:34:02 -070051 private static final boolean VDBG = false;
Robert Greenwalt3192dec2014-05-27 13:20:24 -070052
53 private static final int BASE = Protocol.BASE_NETWORK_FACTORY;
54 /**
55 * Pass a network request to the bearer. If the bearer believes it can
56 * satisfy the request it should connect to the network and create a
57 * NetworkAgent. Once the NetworkAgent is fully functional it will
58 * register itself with ConnectivityService using registerNetworkAgent.
59 * If the bearer cannot immediately satisfy the request (no network,
60 * user disabled the radio, lower-scored network) it should remember
61 * any NetworkRequests it may be able to satisfy in the future. It may
62 * disregard any that it will never be able to service, for example
63 * those requiring a different bearer.
64 * msg.obj = NetworkRequest
65 * msg.arg1 = score - the score of the any network currently satisfying this
66 * request. If this bearer knows in advance it cannot
67 * exceed this score it should not try to connect, holding the request
68 * for the future.
69 * Note that subsequent events may give a different (lower
70 * or higher) score for this request, transmitted to each
71 * NetworkFactory through additional CMD_REQUEST_NETWORK msgs
72 * with the same NetworkRequest but an updated score.
73 * Also, network conditions may change for this bearer
74 * allowing for a better score in the future.
75 */
76 public static final int CMD_REQUEST_NETWORK = BASE;
77
78 /**
79 * Cancel a network request
80 * msg.obj = NetworkRequest
81 */
82 public static final int CMD_CANCEL_REQUEST = BASE + 1;
83
84 /**
85 * Internally used to set our best-guess score.
86 * msg.arg1 = new score
87 */
88 private static final int CMD_SET_SCORE = BASE + 2;
89
90 /**
91 * Internally used to set our current filter for coarse bandwidth changes with
92 * technology changes.
93 * msg.obj = new filter
94 */
95 private static final int CMD_SET_FILTER = BASE + 3;
96
97 private final Context mContext;
98 private final String LOG_TAG;
99
100 private final SparseArray<NetworkRequestInfo> mNetworkRequests =
101 new SparseArray<NetworkRequestInfo>();
102
103 private int mScore;
104 private NetworkCapabilities mCapabilityFilter;
105
106 private int mRefCount = 0;
107 private Messenger mMessenger = null;
108
109 public NetworkFactory(Looper looper, Context context, String logTag,
110 NetworkCapabilities filter) {
111 super(looper);
112 LOG_TAG = logTag;
113 mContext = context;
114 mCapabilityFilter = filter;
115 }
116
117 public void register() {
118 if (DBG) log("Registering NetworkFactory");
119 if (mMessenger == null) {
120 mMessenger = new Messenger(this);
121 ConnectivityManager.from(mContext).registerNetworkFactory(mMessenger, LOG_TAG);
122 }
123 }
124
125 public void unregister() {
126 if (DBG) log("Unregistering NetworkFactory");
127 if (mMessenger != null) {
128 ConnectivityManager.from(mContext).unregisterNetworkFactory(mMessenger);
129 mMessenger = null;
130 }
131 }
132
133 @Override
134 public void handleMessage(Message msg) {
135 switch (msg.what) {
136 case CMD_REQUEST_NETWORK: {
137 handleAddRequest((NetworkRequest)msg.obj, msg.arg1);
138 break;
139 }
140 case CMD_CANCEL_REQUEST: {
141 handleRemoveRequest((NetworkRequest) msg.obj);
142 break;
143 }
144 case CMD_SET_SCORE: {
145 handleSetScore(msg.arg1);
146 break;
147 }
148 case CMD_SET_FILTER: {
149 handleSetFilter((NetworkCapabilities) msg.obj);
150 break;
151 }
152 }
153 }
154
155 private class NetworkRequestInfo {
156 public final NetworkRequest request;
157 public int score;
158 public boolean requested; // do we have a request outstanding, limited by score
159
160 public NetworkRequestInfo(NetworkRequest request, int score) {
161 this.request = request;
162 this.score = score;
163 this.requested = false;
164 }
Robert Greenwalt3d68dee2015-06-10 20:25:14 -0700165
166 @Override
167 public String toString() {
168 return "{" + request + ", score=" + score + ", requested=" + requested + "}";
169 }
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700170 }
171
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900172 @VisibleForTesting
173 protected void handleAddRequest(NetworkRequest request, int score) {
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700174 NetworkRequestInfo n = mNetworkRequests.get(request.requestId);
175 if (n == null) {
Robert Greenwaltfc0c6892014-08-27 14:34:02 -0700176 if (DBG) log("got request " + request + " with score " + score);
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700177 n = new NetworkRequestInfo(request, score);
178 mNetworkRequests.put(n.request.requestId, n);
179 } else {
Robert Greenwaltfc0c6892014-08-27 14:34:02 -0700180 if (VDBG) log("new score " + score + " for exisiting request " + request);
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700181 n.score = score;
182 }
Robert Greenwaltfc0c6892014-08-27 14:34:02 -0700183 if (VDBG) log(" my score=" + mScore + ", my filter=" + mCapabilityFilter);
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700184
185 evalRequest(n);
186 }
187
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900188 @VisibleForTesting
189 protected void handleRemoveRequest(NetworkRequest request) {
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700190 NetworkRequestInfo n = mNetworkRequests.get(request.requestId);
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700191 if (n != null) {
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700192 mNetworkRequests.remove(request.requestId);
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700193 if (n.requested) releaseNetworkFor(n.request);
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700194 }
195 }
196
197 private void handleSetScore(int score) {
198 mScore = score;
199 evalRequests();
200 }
201
202 private void handleSetFilter(NetworkCapabilities netCap) {
203 mCapabilityFilter = netCap;
204 evalRequests();
205 }
206
207 /**
208 * Overridable function to provide complex filtering.
209 * Called for every request every time a new NetworkRequest is seen
210 * and whenever the filterScore or filterNetworkCapabilities change.
211 *
212 * acceptRequest can be overriden to provide complex filter behavior
213 * for the incoming requests
214 *
215 * For output, this class will call {@link #needNetworkFor} and
216 * {@link #releaseNetworkFor} for every request that passes the filters.
217 * If you don't need to see every request, you can leave the base
218 * implementations of those two functions and instead override
219 * {@link #startNetwork} and {@link #stopNetwork}.
220 *
221 * If you want to see every score fluctuation on every request, set
222 * your score filter to a very high number and watch {@link #needNetworkFor}.
223 *
224 * @return {@code true} to accept the request.
225 */
226 public boolean acceptRequest(NetworkRequest request, int score) {
227 return true;
228 }
229
230 private void evalRequest(NetworkRequestInfo n) {
Robert Greenwalt2ffe4122014-12-12 12:22:31 -0800231 if (VDBG) log("evalRequest");
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700232 if (n.requested == false && n.score < mScore &&
233 n.request.networkCapabilities.satisfiedByNetworkCapabilities(
234 mCapabilityFilter) && acceptRequest(n.request, n.score)) {
Robert Greenwalt2ffe4122014-12-12 12:22:31 -0800235 if (VDBG) log(" needNetworkFor");
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700236 needNetworkFor(n.request, n.score);
237 n.requested = true;
238 } else if (n.requested == true &&
239 (n.score > mScore || n.request.networkCapabilities.satisfiedByNetworkCapabilities(
240 mCapabilityFilter) == false || acceptRequest(n.request, n.score) == false)) {
Robert Greenwalt2ffe4122014-12-12 12:22:31 -0800241 if (VDBG) log(" releaseNetworkFor");
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700242 releaseNetworkFor(n.request);
243 n.requested = false;
Robert Greenwalt2ffe4122014-12-12 12:22:31 -0800244 } else {
245 if (VDBG) log(" done");
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700246 }
247 }
248
249 private void evalRequests() {
250 for (int i = 0; i < mNetworkRequests.size(); i++) {
251 NetworkRequestInfo n = mNetworkRequests.valueAt(i);
252
253 evalRequest(n);
254 }
255 }
256
257 // override to do simple mode (request independent)
258 protected void startNetwork() { }
259 protected void stopNetwork() { }
260
261 // override to do fancier stuff
262 protected void needNetworkFor(NetworkRequest networkRequest, int score) {
263 if (++mRefCount == 1) startNetwork();
264 }
265
266 protected void releaseNetworkFor(NetworkRequest networkRequest) {
267 if (--mRefCount == 0) stopNetwork();
268 }
269
270
271 public void addNetworkRequest(NetworkRequest networkRequest, int score) {
272 sendMessage(obtainMessage(CMD_REQUEST_NETWORK,
273 new NetworkRequestInfo(networkRequest, score)));
274 }
275
276 public void removeNetworkRequest(NetworkRequest networkRequest) {
277 sendMessage(obtainMessage(CMD_CANCEL_REQUEST, networkRequest));
278 }
279
280 public void setScoreFilter(int score) {
281 sendMessage(obtainMessage(CMD_SET_SCORE, score, 0));
282 }
283
284 public void setCapabilityFilter(NetworkCapabilities netCap) {
285 sendMessage(obtainMessage(CMD_SET_FILTER, new NetworkCapabilities(netCap)));
286 }
287
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700288 @VisibleForTesting
289 protected int getRequestCount() {
290 return mNetworkRequests.size();
291 }
292
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700293 protected void log(String s) {
294 Log.d(LOG_TAG, s);
295 }
Robert Greenwalt6b746b52014-12-10 14:17:47 -0800296
Robert Greenwalt3d68dee2015-06-10 20:25:14 -0700297 public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
298 final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ");
299 pw.println(toString());
300 pw.increaseIndent();
301 for (int i = 0; i < mNetworkRequests.size(); i++) {
302 pw.println(mNetworkRequests.valueAt(i));
303 }
304 pw.decreaseIndent();
305 }
306
Robert Greenwalt6b746b52014-12-10 14:17:47 -0800307 @Override
308 public String toString() {
309 StringBuilder sb = new StringBuilder("{").append(LOG_TAG).append(" - ScoreFilter=").
310 append(mScore).append(", Filter=").append(mCapabilityFilter).append(", requests=").
Robert Greenwalt3d68dee2015-06-10 20:25:14 -0700311 append(mNetworkRequests.size()).append(", refCount=").append(mRefCount).
312 append("}");
Robert Greenwalt6b746b52014-12-10 14:17:47 -0800313 return sb.toString();
314 }
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700315}