blob: 42ab9256a6ab7a77fd9d0217a6fc23c7b04724bc [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
Artur Satayev26958002019-12-10 17:47:52 +000019import android.compat.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;
Etan Cohenae574a82019-01-08 12:09:18 -080030import com.android.internal.util.AsyncChannel;
Robert Greenwalt3d68dee2015-06-10 20:25:14 -070031import com.android.internal.util.IndentingPrintWriter;
Robert Greenwalt3192dec2014-05-27 13:20:24 -070032import com.android.internal.util.Protocol;
33
Robert Greenwalt3d68dee2015-06-10 20:25:14 -070034import java.io.FileDescriptor;
35import java.io.PrintWriter;
Etan Cohenae574a82019-01-08 12:09:18 -080036import java.util.ArrayList;
Chalard Jean08577fc2018-05-02 21:14:54 +090037import java.util.concurrent.atomic.AtomicInteger;
Robert Greenwalt3d68dee2015-06-10 20:25:14 -070038
Robert Greenwalt3192dec2014-05-27 13:20:24 -070039/**
40 * A NetworkFactory is an entity that creates NetworkAgent objects.
41 * The bearers register with ConnectivityService using {@link #register} and
42 * their factory will start receiving scored NetworkRequests. NetworkRequests
43 * can be filtered 3 ways: by NetworkCapabilities, by score and more complexly by
44 * overridden function. All of these can be dynamic - changing NetworkCapabilities
45 * or score forces re-evaluation of all current requests.
46 *
47 * If any requests pass the filter some overrideable functions will be called.
48 * If the bearer only cares about very simple start/stopNetwork callbacks, those
49 * functions can be overridden. If the bearer needs more interaction, it can
50 * override addNetworkRequest and removeNetworkRequest which will give it each
51 * request that passes their current filters.
52 * @hide
53 **/
54public class NetworkFactory extends Handler {
Chalard Jean08577fc2018-05-02 21:14:54 +090055 /** @hide */
56 public static class SerialNumber {
57 // Guard used by no network factory.
58 public static final int NONE = -1;
59 // A hardcoded serial number for NetworkAgents representing VPNs. These agents are
60 // not created by any factory, so they use this constant for clarity instead of NONE.
61 public static final int VPN = -2;
62 private static final AtomicInteger sNetworkFactorySerialNumber = new AtomicInteger(1);
63 /** Returns a unique serial number for a factory. */
64 public static final int nextSerialNumber() {
65 return sNetworkFactorySerialNumber.getAndIncrement();
66 }
67 }
68
Robert Greenwalt3192dec2014-05-27 13:20:24 -070069 private static final boolean DBG = true;
Robert Greenwaltfc0c6892014-08-27 14:34:02 -070070 private static final boolean VDBG = false;
Robert Greenwalt3192dec2014-05-27 13:20:24 -070071
72 private static final int BASE = Protocol.BASE_NETWORK_FACTORY;
73 /**
74 * Pass a network request to the bearer. If the bearer believes it can
75 * satisfy the request it should connect to the network and create a
76 * NetworkAgent. Once the NetworkAgent is fully functional it will
77 * register itself with ConnectivityService using registerNetworkAgent.
78 * If the bearer cannot immediately satisfy the request (no network,
79 * user disabled the radio, lower-scored network) it should remember
80 * any NetworkRequests it may be able to satisfy in the future. It may
81 * disregard any that it will never be able to service, for example
82 * those requiring a different bearer.
83 * msg.obj = NetworkRequest
Chalard Jean08577fc2018-05-02 21:14:54 +090084 * msg.arg1 = score - the score of the network currently satisfying this
Robert Greenwalt3192dec2014-05-27 13:20:24 -070085 * request. If this bearer knows in advance it cannot
86 * exceed this score it should not try to connect, holding the request
87 * for the future.
88 * Note that subsequent events may give a different (lower
89 * or higher) score for this request, transmitted to each
90 * NetworkFactory through additional CMD_REQUEST_NETWORK msgs
91 * with the same NetworkRequest but an updated score.
92 * Also, network conditions may change for this bearer
93 * allowing for a better score in the future.
Chalard Jean08577fc2018-05-02 21:14:54 +090094 * msg.arg2 = the serial number of the factory currently responsible for the
95 * NetworkAgent handling this request, or SerialNumber.NONE if none.
Robert Greenwalt3192dec2014-05-27 13:20:24 -070096 */
97 public static final int CMD_REQUEST_NETWORK = BASE;
98
99 /**
100 * Cancel a network request
101 * msg.obj = NetworkRequest
102 */
103 public static final int CMD_CANCEL_REQUEST = BASE + 1;
104
105 /**
106 * Internally used to set our best-guess score.
107 * msg.arg1 = new score
108 */
109 private static final int CMD_SET_SCORE = BASE + 2;
110
111 /**
112 * Internally used to set our current filter for coarse bandwidth changes with
113 * technology changes.
114 * msg.obj = new filter
115 */
116 private static final int CMD_SET_FILTER = BASE + 3;
117
Etan Cohenae574a82019-01-08 12:09:18 -0800118 /**
119 * Sent by NetworkFactory to ConnectivityService to indicate that a request is
120 * unfulfillable.
121 * @see #releaseRequestAsUnfulfillableByAnyFactory(NetworkRequest).
122 */
123 public static final int EVENT_UNFULFILLABLE_REQUEST = BASE + 4;
124
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700125 private final Context mContext;
Etan Cohenae574a82019-01-08 12:09:18 -0800126 private final ArrayList<Message> mPreConnectedQueue = new ArrayList<Message>();
127 private AsyncChannel mAsyncChannel;
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700128 private final String LOG_TAG;
129
130 private final SparseArray<NetworkRequestInfo> mNetworkRequests =
131 new SparseArray<NetworkRequestInfo>();
132
133 private int mScore;
134 private NetworkCapabilities mCapabilityFilter;
135
136 private int mRefCount = 0;
137 private Messenger mMessenger = null;
Chalard Jean08577fc2018-05-02 21:14:54 +0900138 private int mSerialNumber;
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700139
Mathew Inwoodfa3a7462018-08-08 14:52:47 +0100140 @UnsupportedAppUsage
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700141 public NetworkFactory(Looper looper, Context context, String logTag,
142 NetworkCapabilities filter) {
143 super(looper);
144 LOG_TAG = logTag;
145 mContext = context;
146 mCapabilityFilter = filter;
147 }
148
149 public void register() {
150 if (DBG) log("Registering NetworkFactory");
151 if (mMessenger == null) {
152 mMessenger = new Messenger(this);
Chalard Jean08577fc2018-05-02 21:14:54 +0900153 mSerialNumber = ConnectivityManager.from(mContext).registerNetworkFactory(mMessenger,
154 LOG_TAG);
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700155 }
156 }
157
158 public void unregister() {
159 if (DBG) log("Unregistering NetworkFactory");
160 if (mMessenger != null) {
161 ConnectivityManager.from(mContext).unregisterNetworkFactory(mMessenger);
162 mMessenger = null;
163 }
164 }
165
166 @Override
167 public void handleMessage(Message msg) {
168 switch (msg.what) {
Etan Cohenae574a82019-01-08 12:09:18 -0800169 case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: {
170 if (mAsyncChannel != null) {
171 log("Received new connection while already connected!");
172 break;
173 }
174 if (VDBG) log("NetworkFactory fully connected");
175 AsyncChannel ac = new AsyncChannel();
176 ac.connected(null, this, msg.replyTo);
177 ac.replyToMessage(msg, AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED,
178 AsyncChannel.STATUS_SUCCESSFUL);
179 mAsyncChannel = ac;
180 for (Message m : mPreConnectedQueue) {
181 ac.sendMessage(m);
182 }
183 mPreConnectedQueue.clear();
184 break;
185 }
186 case AsyncChannel.CMD_CHANNEL_DISCONNECT: {
187 if (VDBG) log("CMD_CHANNEL_DISCONNECT");
188 if (mAsyncChannel != null) {
189 mAsyncChannel.disconnect();
190 mAsyncChannel = null;
191 }
192 break;
193 }
194 case AsyncChannel.CMD_CHANNEL_DISCONNECTED: {
195 if (DBG) log("NetworkFactory channel lost");
196 mAsyncChannel = null;
197 break;
198 }
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700199 case CMD_REQUEST_NETWORK: {
Chalard Jean08577fc2018-05-02 21:14:54 +0900200 handleAddRequest((NetworkRequest) msg.obj, msg.arg1, msg.arg2);
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700201 break;
202 }
203 case CMD_CANCEL_REQUEST: {
204 handleRemoveRequest((NetworkRequest) msg.obj);
205 break;
206 }
207 case CMD_SET_SCORE: {
208 handleSetScore(msg.arg1);
209 break;
210 }
211 case CMD_SET_FILTER: {
212 handleSetFilter((NetworkCapabilities) msg.obj);
213 break;
214 }
215 }
216 }
217
218 private class NetworkRequestInfo {
219 public final NetworkRequest request;
220 public int score;
221 public boolean requested; // do we have a request outstanding, limited by score
Chalard Jean08577fc2018-05-02 21:14:54 +0900222 public int factorySerialNumber;
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700223
Chalard Jean08577fc2018-05-02 21:14:54 +0900224 NetworkRequestInfo(NetworkRequest request, int score, int factorySerialNumber) {
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700225 this.request = request;
226 this.score = score;
227 this.requested = false;
Chalard Jean08577fc2018-05-02 21:14:54 +0900228 this.factorySerialNumber = factorySerialNumber;
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700229 }
Robert Greenwalt3d68dee2015-06-10 20:25:14 -0700230
231 @Override
232 public String toString() {
233 return "{" + request + ", score=" + score + ", requested=" + requested + "}";
234 }
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700235 }
236
Chalard Jean08577fc2018-05-02 21:14:54 +0900237 /**
238 * Add a NetworkRequest that the bearer may want to attempt to satisfy.
239 * @see #CMD_REQUEST_NETWORK
240 *
241 * @param request the request to handle.
242 * @param score the score of the NetworkAgent currently satisfying this request.
243 * @param servingFactorySerialNumber the serial number of the NetworkFactory that
244 * created the NetworkAgent currently satisfying this request.
245 */
246 // TODO : remove this method. It is a stopgap measure to help sheperding a number
247 // of dependent changes that would conflict throughout the automerger graph. Having this
248 // temporarily helps with the process of going through with all these dependent changes across
249 // the entire tree.
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900250 @VisibleForTesting
251 protected void handleAddRequest(NetworkRequest request, int score) {
Chalard Jean08577fc2018-05-02 21:14:54 +0900252 handleAddRequest(request, score, SerialNumber.NONE);
253 }
254
255 /**
256 * Add a NetworkRequest that the bearer may want to attempt to satisfy.
257 * @see #CMD_REQUEST_NETWORK
258 *
259 * @param request the request to handle.
260 * @param score the score of the NetworkAgent currently satisfying this request.
261 * @param servingFactorySerialNumber the serial number of the NetworkFactory that
262 * created the NetworkAgent currently satisfying this request.
263 */
264 @VisibleForTesting
265 protected void handleAddRequest(NetworkRequest request, int score,
266 int servingFactorySerialNumber) {
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700267 NetworkRequestInfo n = mNetworkRequests.get(request.requestId);
268 if (n == null) {
Chalard Jean08577fc2018-05-02 21:14:54 +0900269 if (DBG) {
270 log("got request " + request + " with score " + score
271 + " and serial " + servingFactorySerialNumber);
272 }
273 n = new NetworkRequestInfo(request, score, servingFactorySerialNumber);
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700274 mNetworkRequests.put(n.request.requestId, n);
275 } else {
Chalard Jean08577fc2018-05-02 21:14:54 +0900276 if (VDBG) {
277 log("new score " + score + " for exisiting request " + request
278 + " with serial " + servingFactorySerialNumber);
279 }
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700280 n.score = score;
Chalard Jean08577fc2018-05-02 21:14:54 +0900281 n.factorySerialNumber = servingFactorySerialNumber;
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700282 }
Robert Greenwaltfc0c6892014-08-27 14:34:02 -0700283 if (VDBG) log(" my score=" + mScore + ", my filter=" + mCapabilityFilter);
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700284
285 evalRequest(n);
286 }
287
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900288 @VisibleForTesting
289 protected void handleRemoveRequest(NetworkRequest request) {
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700290 NetworkRequestInfo n = mNetworkRequests.get(request.requestId);
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700291 if (n != null) {
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700292 mNetworkRequests.remove(request.requestId);
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700293 if (n.requested) releaseNetworkFor(n.request);
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700294 }
295 }
296
297 private void handleSetScore(int score) {
298 mScore = score;
299 evalRequests();
300 }
301
302 private void handleSetFilter(NetworkCapabilities netCap) {
303 mCapabilityFilter = netCap;
304 evalRequests();
305 }
306
307 /**
308 * Overridable function to provide complex filtering.
309 * Called for every request every time a new NetworkRequest is seen
310 * and whenever the filterScore or filterNetworkCapabilities change.
311 *
koprivadebd4ee2018-09-13 10:59:46 -0700312 * acceptRequest can be overridden to provide complex filter behavior
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700313 * for the incoming requests
314 *
315 * For output, this class will call {@link #needNetworkFor} and
316 * {@link #releaseNetworkFor} for every request that passes the filters.
317 * If you don't need to see every request, you can leave the base
318 * implementations of those two functions and instead override
319 * {@link #startNetwork} and {@link #stopNetwork}.
320 *
321 * If you want to see every score fluctuation on every request, set
322 * your score filter to a very high number and watch {@link #needNetworkFor}.
323 *
324 * @return {@code true} to accept the request.
325 */
326 public boolean acceptRequest(NetworkRequest request, int score) {
327 return true;
328 }
329
330 private void evalRequest(NetworkRequestInfo n) {
Chalard Jean08577fc2018-05-02 21:14:54 +0900331 if (VDBG) {
332 log("evalRequest");
333 log(" n.requests = " + n.requested);
334 log(" n.score = " + n.score);
335 log(" mScore = " + mScore);
336 log(" n.factorySerialNumber = " + n.factorySerialNumber);
337 log(" mSerialNumber = " + mSerialNumber);
338 }
339 if (shouldNeedNetworkFor(n)) {
Robert Greenwalt2ffe4122014-12-12 12:22:31 -0800340 if (VDBG) log(" needNetworkFor");
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700341 needNetworkFor(n.request, n.score);
342 n.requested = true;
Chalard Jean08577fc2018-05-02 21:14:54 +0900343 } else if (shouldReleaseNetworkFor(n)) {
Robert Greenwalt2ffe4122014-12-12 12:22:31 -0800344 if (VDBG) log(" releaseNetworkFor");
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700345 releaseNetworkFor(n.request);
346 n.requested = false;
Robert Greenwalt2ffe4122014-12-12 12:22:31 -0800347 } else {
348 if (VDBG) log(" done");
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700349 }
350 }
351
Chalard Jean08577fc2018-05-02 21:14:54 +0900352 private boolean shouldNeedNetworkFor(NetworkRequestInfo n) {
353 // If this request is already tracked, it doesn't qualify for need
354 return !n.requested
355 // If the score of this request is higher or equal to that of this factory and some
356 // other factory is responsible for it, then this factory should not track the request
357 // because it has no hope of satisfying it.
358 && (n.score < mScore || n.factorySerialNumber == mSerialNumber)
359 // If this factory can't satisfy the capability needs of this request, then it
360 // should not be tracked.
361 && n.request.networkCapabilities.satisfiedByNetworkCapabilities(mCapabilityFilter)
362 // Finally if the concrete implementation of the factory rejects the request, then
363 // don't track it.
364 && acceptRequest(n.request, n.score);
365 }
366
367 private boolean shouldReleaseNetworkFor(NetworkRequestInfo n) {
368 // Don't release a request that's not tracked.
369 return n.requested
370 // The request should be released if it can't be satisfied by this factory. That
371 // means either of the following conditions are met :
372 // - Its score is too high to be satisfied by this factory and it's not already
373 // assigned to the factory
374 // - This factory can't satisfy the capability needs of the request
375 // - The concrete implementation of the factory rejects the request
376 && ((n.score > mScore && n.factorySerialNumber != mSerialNumber)
377 || !n.request.networkCapabilities.satisfiedByNetworkCapabilities(
378 mCapabilityFilter)
379 || !acceptRequest(n.request, n.score));
380 }
381
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700382 private void evalRequests() {
383 for (int i = 0; i < mNetworkRequests.size(); i++) {
384 NetworkRequestInfo n = mNetworkRequests.valueAt(i);
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700385 evalRequest(n);
386 }
387 }
388
Etan Cohen896c5742017-08-23 08:39:31 -0700389 /**
390 * Post a command, on this NetworkFactory Handler, to re-evaluate all
391 * oustanding requests. Can be called from a factory implementation.
392 */
393 protected void reevaluateAllRequests() {
394 post(() -> {
395 evalRequests();
396 });
397 }
398
Etan Cohenae574a82019-01-08 12:09:18 -0800399 /**
400 * Can be called by a factory to release a request as unfulfillable: the request will be
401 * removed, and the caller will get a
402 * {@link ConnectivityManager.NetworkCallback#onUnavailable()} callback after this function
403 * returns.
404 *
405 * Note: this should only be called by factory which KNOWS that it is the ONLY factory which
406 * is able to fulfill this request!
407 */
408 protected void releaseRequestAsUnfulfillableByAnyFactory(NetworkRequest r) {
409 post(() -> {
410 if (DBG) log("releaseRequestAsUnfulfillableByAnyFactory: " + r);
411 Message msg = obtainMessage(EVENT_UNFULFILLABLE_REQUEST, r);
412 if (mAsyncChannel != null) {
413 mAsyncChannel.sendMessage(msg);
414 } else {
415 mPreConnectedQueue.add(msg);
416 }
417 });
418 }
419
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700420 // override to do simple mode (request independent)
421 protected void startNetwork() { }
422 protected void stopNetwork() { }
423
424 // override to do fancier stuff
425 protected void needNetworkFor(NetworkRequest networkRequest, int score) {
426 if (++mRefCount == 1) startNetwork();
427 }
428
429 protected void releaseNetworkFor(NetworkRequest networkRequest) {
430 if (--mRefCount == 0) stopNetwork();
431 }
432
Mathew Inwood31755f92018-12-20 13:53:36 +0000433 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700434 public void setScoreFilter(int score) {
435 sendMessage(obtainMessage(CMD_SET_SCORE, score, 0));
436 }
437
438 public void setCapabilityFilter(NetworkCapabilities netCap) {
439 sendMessage(obtainMessage(CMD_SET_FILTER, new NetworkCapabilities(netCap)));
440 }
441
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700442 @VisibleForTesting
443 protected int getRequestCount() {
444 return mNetworkRequests.size();
445 }
446
Chalard Jean08577fc2018-05-02 21:14:54 +0900447 public int getSerialNumber() {
448 return mSerialNumber;
449 }
450
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700451 protected void log(String s) {
452 Log.d(LOG_TAG, s);
453 }
Robert Greenwalt6b746b52014-12-10 14:17:47 -0800454
Mathew Inwood31755f92018-12-20 13:53:36 +0000455 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Robert Greenwalt3d68dee2015-06-10 20:25:14 -0700456 public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
457 final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ");
458 pw.println(toString());
459 pw.increaseIndent();
460 for (int i = 0; i < mNetworkRequests.size(); i++) {
461 pw.println(mNetworkRequests.valueAt(i));
462 }
463 pw.decreaseIndent();
464 }
465
Robert Greenwalt6b746b52014-12-10 14:17:47 -0800466 @Override
467 public String toString() {
Chalard Jean08577fc2018-05-02 21:14:54 +0900468 StringBuilder sb = new StringBuilder("{").append(LOG_TAG).append(" - mSerialNumber=")
469 .append(mSerialNumber).append(", ScoreFilter=")
470 .append(mScore).append(", Filter=").append(mCapabilityFilter).append(", requests=")
471 .append(mNetworkRequests.size()).append(", refCount=").append(mRefCount)
472 .append("}");
Robert Greenwalt6b746b52014-12-10 14:17:47 -0800473 return sb.toString();
474 }
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700475}