blob: 0dfe7a495738a3531eafcfc9c4fcd31bca490722 [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
Mathew Inwoodfa3a7462018-08-08 14:52:47 +010019import android.annotation.UnsupportedAppUsage;
Robert Greenwalt3192dec2014-05-27 13:20:24 -070020import android.content.Context;
Mathew Inwood31755f92018-12-20 13:53:36 +000021import android.os.Build;
Robert Greenwalt3192dec2014-05-27 13:20:24 -070022import android.os.Handler;
23import android.os.Looper;
24import android.os.Message;
25import android.os.Messenger;
Robert Greenwalt3192dec2014-05-27 13:20:24 -070026import android.util.Log;
27import android.util.SparseArray;
28
Robert Greenwalt348e98d2015-06-05 17:55:36 -070029import com.android.internal.annotations.VisibleForTesting;
Robert Greenwalt3d68dee2015-06-10 20:25:14 -070030import com.android.internal.util.IndentingPrintWriter;
Robert Greenwalt3192dec2014-05-27 13:20:24 -070031import com.android.internal.util.Protocol;
32
Robert Greenwalt3d68dee2015-06-10 20:25:14 -070033import java.io.FileDescriptor;
34import java.io.PrintWriter;
Chalard Jean08577fc2018-05-02 21:14:54 +090035import java.util.concurrent.atomic.AtomicInteger;
Robert Greenwalt3d68dee2015-06-10 20:25:14 -070036
Robert Greenwalt3192dec2014-05-27 13:20:24 -070037/**
38 * A NetworkFactory is an entity that creates NetworkAgent objects.
39 * The bearers register with ConnectivityService using {@link #register} and
40 * their factory will start receiving scored NetworkRequests. NetworkRequests
41 * can be filtered 3 ways: by NetworkCapabilities, by score and more complexly by
42 * overridden function. All of these can be dynamic - changing NetworkCapabilities
43 * or score forces re-evaluation of all current requests.
44 *
45 * If any requests pass the filter some overrideable functions will be called.
46 * If the bearer only cares about very simple start/stopNetwork callbacks, those
47 * functions can be overridden. If the bearer needs more interaction, it can
48 * override addNetworkRequest and removeNetworkRequest which will give it each
49 * request that passes their current filters.
50 * @hide
51 **/
52public class NetworkFactory extends Handler {
Chalard Jean08577fc2018-05-02 21:14:54 +090053 /** @hide */
54 public static class SerialNumber {
55 // Guard used by no network factory.
56 public static final int NONE = -1;
57 // A hardcoded serial number for NetworkAgents representing VPNs. These agents are
58 // not created by any factory, so they use this constant for clarity instead of NONE.
59 public static final int VPN = -2;
60 private static final AtomicInteger sNetworkFactorySerialNumber = new AtomicInteger(1);
61 /** Returns a unique serial number for a factory. */
62 public static final int nextSerialNumber() {
63 return sNetworkFactorySerialNumber.getAndIncrement();
64 }
65 }
66
Robert Greenwalt3192dec2014-05-27 13:20:24 -070067 private static final boolean DBG = true;
Robert Greenwaltfc0c6892014-08-27 14:34:02 -070068 private static final boolean VDBG = false;
Robert Greenwalt3192dec2014-05-27 13:20:24 -070069
70 private static final int BASE = Protocol.BASE_NETWORK_FACTORY;
71 /**
72 * Pass a network request to the bearer. If the bearer believes it can
73 * satisfy the request it should connect to the network and create a
74 * NetworkAgent. Once the NetworkAgent is fully functional it will
75 * register itself with ConnectivityService using registerNetworkAgent.
76 * If the bearer cannot immediately satisfy the request (no network,
77 * user disabled the radio, lower-scored network) it should remember
78 * any NetworkRequests it may be able to satisfy in the future. It may
79 * disregard any that it will never be able to service, for example
80 * those requiring a different bearer.
81 * msg.obj = NetworkRequest
Chalard Jean08577fc2018-05-02 21:14:54 +090082 * msg.arg1 = score - the score of the network currently satisfying this
Robert Greenwalt3192dec2014-05-27 13:20:24 -070083 * request. If this bearer knows in advance it cannot
84 * exceed this score it should not try to connect, holding the request
85 * for the future.
86 * Note that subsequent events may give a different (lower
87 * or higher) score for this request, transmitted to each
88 * NetworkFactory through additional CMD_REQUEST_NETWORK msgs
89 * with the same NetworkRequest but an updated score.
90 * Also, network conditions may change for this bearer
91 * allowing for a better score in the future.
Chalard Jean08577fc2018-05-02 21:14:54 +090092 * msg.arg2 = the serial number of the factory currently responsible for the
93 * NetworkAgent handling this request, or SerialNumber.NONE if none.
Robert Greenwalt3192dec2014-05-27 13:20:24 -070094 */
95 public static final int CMD_REQUEST_NETWORK = BASE;
96
97 /**
98 * Cancel a network request
99 * msg.obj = NetworkRequest
100 */
101 public static final int CMD_CANCEL_REQUEST = BASE + 1;
102
103 /**
104 * Internally used to set our best-guess score.
105 * msg.arg1 = new score
106 */
107 private static final int CMD_SET_SCORE = BASE + 2;
108
109 /**
110 * Internally used to set our current filter for coarse bandwidth changes with
111 * technology changes.
112 * msg.obj = new filter
113 */
114 private static final int CMD_SET_FILTER = BASE + 3;
115
116 private final Context mContext;
117 private final String LOG_TAG;
118
119 private final SparseArray<NetworkRequestInfo> mNetworkRequests =
120 new SparseArray<NetworkRequestInfo>();
121
122 private int mScore;
123 private NetworkCapabilities mCapabilityFilter;
124
125 private int mRefCount = 0;
126 private Messenger mMessenger = null;
Chalard Jean08577fc2018-05-02 21:14:54 +0900127 private int mSerialNumber;
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700128
Mathew Inwoodfa3a7462018-08-08 14:52:47 +0100129 @UnsupportedAppUsage
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700130 public NetworkFactory(Looper looper, Context context, String logTag,
131 NetworkCapabilities filter) {
132 super(looper);
133 LOG_TAG = logTag;
134 mContext = context;
135 mCapabilityFilter = filter;
136 }
137
138 public void register() {
139 if (DBG) log("Registering NetworkFactory");
140 if (mMessenger == null) {
141 mMessenger = new Messenger(this);
Chalard Jean08577fc2018-05-02 21:14:54 +0900142 mSerialNumber = ConnectivityManager.from(mContext).registerNetworkFactory(mMessenger,
143 LOG_TAG);
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700144 }
145 }
146
147 public void unregister() {
148 if (DBG) log("Unregistering NetworkFactory");
149 if (mMessenger != null) {
150 ConnectivityManager.from(mContext).unregisterNetworkFactory(mMessenger);
151 mMessenger = null;
152 }
153 }
154
155 @Override
156 public void handleMessage(Message msg) {
157 switch (msg.what) {
158 case CMD_REQUEST_NETWORK: {
Chalard Jean08577fc2018-05-02 21:14:54 +0900159 handleAddRequest((NetworkRequest) msg.obj, msg.arg1, msg.arg2);
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700160 break;
161 }
162 case CMD_CANCEL_REQUEST: {
163 handleRemoveRequest((NetworkRequest) msg.obj);
164 break;
165 }
166 case CMD_SET_SCORE: {
167 handleSetScore(msg.arg1);
168 break;
169 }
170 case CMD_SET_FILTER: {
171 handleSetFilter((NetworkCapabilities) msg.obj);
172 break;
173 }
174 }
175 }
176
177 private class NetworkRequestInfo {
178 public final NetworkRequest request;
179 public int score;
180 public boolean requested; // do we have a request outstanding, limited by score
Chalard Jean08577fc2018-05-02 21:14:54 +0900181 public int factorySerialNumber;
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700182
Chalard Jean08577fc2018-05-02 21:14:54 +0900183 NetworkRequestInfo(NetworkRequest request, int score, int factorySerialNumber) {
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700184 this.request = request;
185 this.score = score;
186 this.requested = false;
Chalard Jean08577fc2018-05-02 21:14:54 +0900187 this.factorySerialNumber = factorySerialNumber;
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700188 }
Robert Greenwalt3d68dee2015-06-10 20:25:14 -0700189
190 @Override
191 public String toString() {
192 return "{" + request + ", score=" + score + ", requested=" + requested + "}";
193 }
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700194 }
195
Chalard Jean08577fc2018-05-02 21:14:54 +0900196 /**
197 * Add a NetworkRequest that the bearer may want to attempt to satisfy.
198 * @see #CMD_REQUEST_NETWORK
199 *
200 * @param request the request to handle.
201 * @param score the score of the NetworkAgent currently satisfying this request.
202 * @param servingFactorySerialNumber the serial number of the NetworkFactory that
203 * created the NetworkAgent currently satisfying this request.
204 */
205 // TODO : remove this method. It is a stopgap measure to help sheperding a number
206 // of dependent changes that would conflict throughout the automerger graph. Having this
207 // temporarily helps with the process of going through with all these dependent changes across
208 // the entire tree.
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900209 @VisibleForTesting
210 protected void handleAddRequest(NetworkRequest request, int score) {
Chalard Jean08577fc2018-05-02 21:14:54 +0900211 handleAddRequest(request, score, SerialNumber.NONE);
212 }
213
214 /**
215 * Add a NetworkRequest that the bearer may want to attempt to satisfy.
216 * @see #CMD_REQUEST_NETWORK
217 *
218 * @param request the request to handle.
219 * @param score the score of the NetworkAgent currently satisfying this request.
220 * @param servingFactorySerialNumber the serial number of the NetworkFactory that
221 * created the NetworkAgent currently satisfying this request.
222 */
223 @VisibleForTesting
224 protected void handleAddRequest(NetworkRequest request, int score,
225 int servingFactorySerialNumber) {
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700226 NetworkRequestInfo n = mNetworkRequests.get(request.requestId);
227 if (n == null) {
Chalard Jean08577fc2018-05-02 21:14:54 +0900228 if (DBG) {
229 log("got request " + request + " with score " + score
230 + " and serial " + servingFactorySerialNumber);
231 }
232 n = new NetworkRequestInfo(request, score, servingFactorySerialNumber);
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700233 mNetworkRequests.put(n.request.requestId, n);
234 } else {
Chalard Jean08577fc2018-05-02 21:14:54 +0900235 if (VDBG) {
236 log("new score " + score + " for exisiting request " + request
237 + " with serial " + servingFactorySerialNumber);
238 }
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700239 n.score = score;
Chalard Jean08577fc2018-05-02 21:14:54 +0900240 n.factorySerialNumber = servingFactorySerialNumber;
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700241 }
Robert Greenwaltfc0c6892014-08-27 14:34:02 -0700242 if (VDBG) log(" my score=" + mScore + ", my filter=" + mCapabilityFilter);
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700243
244 evalRequest(n);
245 }
246
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900247 @VisibleForTesting
248 protected void handleRemoveRequest(NetworkRequest request) {
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700249 NetworkRequestInfo n = mNetworkRequests.get(request.requestId);
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700250 if (n != null) {
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700251 mNetworkRequests.remove(request.requestId);
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700252 if (n.requested) releaseNetworkFor(n.request);
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700253 }
254 }
255
256 private void handleSetScore(int score) {
257 mScore = score;
258 evalRequests();
259 }
260
261 private void handleSetFilter(NetworkCapabilities netCap) {
262 mCapabilityFilter = netCap;
263 evalRequests();
264 }
265
266 /**
267 * Overridable function to provide complex filtering.
268 * Called for every request every time a new NetworkRequest is seen
269 * and whenever the filterScore or filterNetworkCapabilities change.
270 *
koprivadebd4ee2018-09-13 10:59:46 -0700271 * acceptRequest can be overridden to provide complex filter behavior
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700272 * for the incoming requests
273 *
274 * For output, this class will call {@link #needNetworkFor} and
275 * {@link #releaseNetworkFor} for every request that passes the filters.
276 * If you don't need to see every request, you can leave the base
277 * implementations of those two functions and instead override
278 * {@link #startNetwork} and {@link #stopNetwork}.
279 *
280 * If you want to see every score fluctuation on every request, set
281 * your score filter to a very high number and watch {@link #needNetworkFor}.
282 *
283 * @return {@code true} to accept the request.
284 */
285 public boolean acceptRequest(NetworkRequest request, int score) {
286 return true;
287 }
288
289 private void evalRequest(NetworkRequestInfo n) {
Chalard Jean08577fc2018-05-02 21:14:54 +0900290 if (VDBG) {
291 log("evalRequest");
292 log(" n.requests = " + n.requested);
293 log(" n.score = " + n.score);
294 log(" mScore = " + mScore);
295 log(" n.factorySerialNumber = " + n.factorySerialNumber);
296 log(" mSerialNumber = " + mSerialNumber);
297 }
298 if (shouldNeedNetworkFor(n)) {
Robert Greenwalt2ffe4122014-12-12 12:22:31 -0800299 if (VDBG) log(" needNetworkFor");
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700300 needNetworkFor(n.request, n.score);
301 n.requested = true;
Chalard Jean08577fc2018-05-02 21:14:54 +0900302 } else if (shouldReleaseNetworkFor(n)) {
Robert Greenwalt2ffe4122014-12-12 12:22:31 -0800303 if (VDBG) log(" releaseNetworkFor");
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700304 releaseNetworkFor(n.request);
305 n.requested = false;
Robert Greenwalt2ffe4122014-12-12 12:22:31 -0800306 } else {
307 if (VDBG) log(" done");
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700308 }
309 }
310
Chalard Jean08577fc2018-05-02 21:14:54 +0900311 private boolean shouldNeedNetworkFor(NetworkRequestInfo n) {
312 // If this request is already tracked, it doesn't qualify for need
313 return !n.requested
314 // If the score of this request is higher or equal to that of this factory and some
315 // other factory is responsible for it, then this factory should not track the request
316 // because it has no hope of satisfying it.
317 && (n.score < mScore || n.factorySerialNumber == mSerialNumber)
318 // If this factory can't satisfy the capability needs of this request, then it
319 // should not be tracked.
320 && n.request.networkCapabilities.satisfiedByNetworkCapabilities(mCapabilityFilter)
321 // Finally if the concrete implementation of the factory rejects the request, then
322 // don't track it.
323 && acceptRequest(n.request, n.score);
324 }
325
326 private boolean shouldReleaseNetworkFor(NetworkRequestInfo n) {
327 // Don't release a request that's not tracked.
328 return n.requested
329 // The request should be released if it can't be satisfied by this factory. That
330 // means either of the following conditions are met :
331 // - Its score is too high to be satisfied by this factory and it's not already
332 // assigned to the factory
333 // - This factory can't satisfy the capability needs of the request
334 // - The concrete implementation of the factory rejects the request
335 && ((n.score > mScore && n.factorySerialNumber != mSerialNumber)
336 || !n.request.networkCapabilities.satisfiedByNetworkCapabilities(
337 mCapabilityFilter)
338 || !acceptRequest(n.request, n.score));
339 }
340
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700341 private void evalRequests() {
342 for (int i = 0; i < mNetworkRequests.size(); i++) {
343 NetworkRequestInfo n = mNetworkRequests.valueAt(i);
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700344 evalRequest(n);
345 }
346 }
347
Etan Cohen896c5742017-08-23 08:39:31 -0700348 /**
349 * Post a command, on this NetworkFactory Handler, to re-evaluate all
350 * oustanding requests. Can be called from a factory implementation.
351 */
352 protected void reevaluateAllRequests() {
353 post(() -> {
354 evalRequests();
355 });
356 }
357
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700358 // override to do simple mode (request independent)
359 protected void startNetwork() { }
360 protected void stopNetwork() { }
361
362 // override to do fancier stuff
363 protected void needNetworkFor(NetworkRequest networkRequest, int score) {
364 if (++mRefCount == 1) startNetwork();
365 }
366
367 protected void releaseNetworkFor(NetworkRequest networkRequest) {
368 if (--mRefCount == 0) stopNetwork();
369 }
370
Mathew Inwood31755f92018-12-20 13:53:36 +0000371 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700372 public void setScoreFilter(int score) {
373 sendMessage(obtainMessage(CMD_SET_SCORE, score, 0));
374 }
375
376 public void setCapabilityFilter(NetworkCapabilities netCap) {
377 sendMessage(obtainMessage(CMD_SET_FILTER, new NetworkCapabilities(netCap)));
378 }
379
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700380 @VisibleForTesting
381 protected int getRequestCount() {
382 return mNetworkRequests.size();
383 }
384
Chalard Jean08577fc2018-05-02 21:14:54 +0900385 public int getSerialNumber() {
386 return mSerialNumber;
387 }
388
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700389 protected void log(String s) {
390 Log.d(LOG_TAG, s);
391 }
Robert Greenwalt6b746b52014-12-10 14:17:47 -0800392
Mathew Inwood31755f92018-12-20 13:53:36 +0000393 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Robert Greenwalt3d68dee2015-06-10 20:25:14 -0700394 public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
395 final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ");
396 pw.println(toString());
397 pw.increaseIndent();
398 for (int i = 0; i < mNetworkRequests.size(); i++) {
399 pw.println(mNetworkRequests.valueAt(i));
400 }
401 pw.decreaseIndent();
402 }
403
Robert Greenwalt6b746b52014-12-10 14:17:47 -0800404 @Override
405 public String toString() {
Chalard Jean08577fc2018-05-02 21:14:54 +0900406 StringBuilder sb = new StringBuilder("{").append(LOG_TAG).append(" - mSerialNumber=")
407 .append(mSerialNumber).append(", ScoreFilter=")
408 .append(mScore).append(", Filter=").append(mCapabilityFilter).append(", requests=")
409 .append(mNetworkRequests.size()).append(", refCount=").append(mRefCount)
410 .append("}");
Robert Greenwalt6b746b52014-12-10 14:17:47 -0800411 return sb.toString();
412 }
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700413}