blob: 181cab41e9288d0136448fb50d5780e7cea251ce [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 Inwood55418ea2018-12-20 15:30:45 +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;
35
Robert Greenwalt3192dec2014-05-27 13:20:24 -070036/**
37 * A NetworkFactory is an entity that creates NetworkAgent objects.
38 * The bearers register with ConnectivityService using {@link #register} and
39 * their factory will start receiving scored NetworkRequests. NetworkRequests
40 * can be filtered 3 ways: by NetworkCapabilities, by score and more complexly by
41 * overridden function. All of these can be dynamic - changing NetworkCapabilities
42 * or score forces re-evaluation of all current requests.
43 *
44 * If any requests pass the filter some overrideable functions will be called.
45 * If the bearer only cares about very simple start/stopNetwork callbacks, those
46 * functions can be overridden. If the bearer needs more interaction, it can
47 * override addNetworkRequest and removeNetworkRequest which will give it each
48 * request that passes their current filters.
49 * @hide
50 **/
51public class NetworkFactory extends Handler {
52 private static final boolean DBG = true;
Robert Greenwaltfc0c6892014-08-27 14:34:02 -070053 private static final boolean VDBG = false;
Robert Greenwalt3192dec2014-05-27 13:20:24 -070054
55 private static final int BASE = Protocol.BASE_NETWORK_FACTORY;
56 /**
57 * Pass a network request to the bearer. If the bearer believes it can
58 * satisfy the request it should connect to the network and create a
59 * NetworkAgent. Once the NetworkAgent is fully functional it will
60 * register itself with ConnectivityService using registerNetworkAgent.
61 * If the bearer cannot immediately satisfy the request (no network,
62 * user disabled the radio, lower-scored network) it should remember
63 * any NetworkRequests it may be able to satisfy in the future. It may
64 * disregard any that it will never be able to service, for example
65 * those requiring a different bearer.
66 * msg.obj = NetworkRequest
67 * msg.arg1 = score - the score of the any network currently satisfying this
68 * request. If this bearer knows in advance it cannot
69 * exceed this score it should not try to connect, holding the request
70 * for the future.
71 * Note that subsequent events may give a different (lower
72 * or higher) score for this request, transmitted to each
73 * NetworkFactory through additional CMD_REQUEST_NETWORK msgs
74 * with the same NetworkRequest but an updated score.
75 * Also, network conditions may change for this bearer
76 * allowing for a better score in the future.
77 */
78 public static final int CMD_REQUEST_NETWORK = BASE;
79
80 /**
81 * Cancel a network request
82 * msg.obj = NetworkRequest
83 */
84 public static final int CMD_CANCEL_REQUEST = BASE + 1;
85
86 /**
87 * Internally used to set our best-guess score.
88 * msg.arg1 = new score
89 */
90 private static final int CMD_SET_SCORE = BASE + 2;
91
92 /**
93 * Internally used to set our current filter for coarse bandwidth changes with
94 * technology changes.
95 * msg.obj = new filter
96 */
97 private static final int CMD_SET_FILTER = BASE + 3;
98
99 private final Context mContext;
100 private final String LOG_TAG;
101
102 private final SparseArray<NetworkRequestInfo> mNetworkRequests =
103 new SparseArray<NetworkRequestInfo>();
104
105 private int mScore;
106 private NetworkCapabilities mCapabilityFilter;
107
108 private int mRefCount = 0;
109 private Messenger mMessenger = null;
110
Mathew Inwoodfa3a7462018-08-08 14:52:47 +0100111 @UnsupportedAppUsage
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700112 public NetworkFactory(Looper looper, Context context, String logTag,
113 NetworkCapabilities filter) {
114 super(looper);
115 LOG_TAG = logTag;
116 mContext = context;
117 mCapabilityFilter = filter;
118 }
119
120 public void register() {
121 if (DBG) log("Registering NetworkFactory");
122 if (mMessenger == null) {
123 mMessenger = new Messenger(this);
124 ConnectivityManager.from(mContext).registerNetworkFactory(mMessenger, LOG_TAG);
125 }
126 }
127
128 public void unregister() {
129 if (DBG) log("Unregistering NetworkFactory");
130 if (mMessenger != null) {
131 ConnectivityManager.from(mContext).unregisterNetworkFactory(mMessenger);
132 mMessenger = null;
133 }
134 }
135
136 @Override
137 public void handleMessage(Message msg) {
138 switch (msg.what) {
139 case CMD_REQUEST_NETWORK: {
140 handleAddRequest((NetworkRequest)msg.obj, msg.arg1);
141 break;
142 }
143 case CMD_CANCEL_REQUEST: {
144 handleRemoveRequest((NetworkRequest) msg.obj);
145 break;
146 }
147 case CMD_SET_SCORE: {
148 handleSetScore(msg.arg1);
149 break;
150 }
151 case CMD_SET_FILTER: {
152 handleSetFilter((NetworkCapabilities) msg.obj);
153 break;
154 }
155 }
156 }
157
158 private class NetworkRequestInfo {
159 public final NetworkRequest request;
160 public int score;
161 public boolean requested; // do we have a request outstanding, limited by score
162
163 public NetworkRequestInfo(NetworkRequest request, int score) {
164 this.request = request;
165 this.score = score;
166 this.requested = false;
167 }
Robert Greenwalt3d68dee2015-06-10 20:25:14 -0700168
169 @Override
170 public String toString() {
171 return "{" + request + ", score=" + score + ", requested=" + requested + "}";
172 }
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700173 }
174
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900175 @VisibleForTesting
176 protected void handleAddRequest(NetworkRequest request, int score) {
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700177 NetworkRequestInfo n = mNetworkRequests.get(request.requestId);
178 if (n == null) {
Robert Greenwaltfc0c6892014-08-27 14:34:02 -0700179 if (DBG) log("got request " + request + " with score " + score);
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700180 n = new NetworkRequestInfo(request, score);
181 mNetworkRequests.put(n.request.requestId, n);
182 } else {
Robert Greenwaltfc0c6892014-08-27 14:34:02 -0700183 if (VDBG) log("new score " + score + " for exisiting request " + request);
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700184 n.score = score;
185 }
Robert Greenwaltfc0c6892014-08-27 14:34:02 -0700186 if (VDBG) log(" my score=" + mScore + ", my filter=" + mCapabilityFilter);
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700187
188 evalRequest(n);
189 }
190
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900191 @VisibleForTesting
192 protected void handleRemoveRequest(NetworkRequest request) {
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700193 NetworkRequestInfo n = mNetworkRequests.get(request.requestId);
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700194 if (n != null) {
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700195 mNetworkRequests.remove(request.requestId);
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700196 if (n.requested) releaseNetworkFor(n.request);
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700197 }
198 }
199
200 private void handleSetScore(int score) {
201 mScore = score;
202 evalRequests();
203 }
204
205 private void handleSetFilter(NetworkCapabilities netCap) {
206 mCapabilityFilter = netCap;
207 evalRequests();
208 }
209
210 /**
211 * Overridable function to provide complex filtering.
212 * Called for every request every time a new NetworkRequest is seen
213 * and whenever the filterScore or filterNetworkCapabilities change.
214 *
koprivadebd4ee2018-09-13 10:59:46 -0700215 * acceptRequest can be overridden to provide complex filter behavior
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700216 * for the incoming requests
217 *
218 * For output, this class will call {@link #needNetworkFor} and
219 * {@link #releaseNetworkFor} for every request that passes the filters.
220 * If you don't need to see every request, you can leave the base
221 * implementations of those two functions and instead override
222 * {@link #startNetwork} and {@link #stopNetwork}.
223 *
224 * If you want to see every score fluctuation on every request, set
225 * your score filter to a very high number and watch {@link #needNetworkFor}.
226 *
227 * @return {@code true} to accept the request.
228 */
229 public boolean acceptRequest(NetworkRequest request, int score) {
230 return true;
231 }
232
233 private void evalRequest(NetworkRequestInfo n) {
Robert Greenwalt2ffe4122014-12-12 12:22:31 -0800234 if (VDBG) log("evalRequest");
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700235 if (n.requested == false && n.score < mScore &&
236 n.request.networkCapabilities.satisfiedByNetworkCapabilities(
237 mCapabilityFilter) && acceptRequest(n.request, n.score)) {
Robert Greenwalt2ffe4122014-12-12 12:22:31 -0800238 if (VDBG) log(" needNetworkFor");
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700239 needNetworkFor(n.request, n.score);
240 n.requested = true;
241 } else if (n.requested == true &&
242 (n.score > mScore || n.request.networkCapabilities.satisfiedByNetworkCapabilities(
243 mCapabilityFilter) == false || acceptRequest(n.request, n.score) == false)) {
Robert Greenwalt2ffe4122014-12-12 12:22:31 -0800244 if (VDBG) log(" releaseNetworkFor");
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700245 releaseNetworkFor(n.request);
246 n.requested = false;
Robert Greenwalt2ffe4122014-12-12 12:22:31 -0800247 } else {
248 if (VDBG) log(" done");
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700249 }
250 }
251
252 private void evalRequests() {
253 for (int i = 0; i < mNetworkRequests.size(); i++) {
254 NetworkRequestInfo n = mNetworkRequests.valueAt(i);
255
256 evalRequest(n);
257 }
258 }
259
Etan Cohen896c5742017-08-23 08:39:31 -0700260 /**
261 * Post a command, on this NetworkFactory Handler, to re-evaluate all
262 * oustanding requests. Can be called from a factory implementation.
263 */
264 protected void reevaluateAllRequests() {
265 post(() -> {
266 evalRequests();
267 });
268 }
269
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700270 // override to do simple mode (request independent)
271 protected void startNetwork() { }
272 protected void stopNetwork() { }
273
274 // override to do fancier stuff
275 protected void needNetworkFor(NetworkRequest networkRequest, int score) {
276 if (++mRefCount == 1) startNetwork();
277 }
278
279 protected void releaseNetworkFor(NetworkRequest networkRequest) {
280 if (--mRefCount == 0) stopNetwork();
281 }
282
283
284 public void addNetworkRequest(NetworkRequest networkRequest, int score) {
285 sendMessage(obtainMessage(CMD_REQUEST_NETWORK,
286 new NetworkRequestInfo(networkRequest, score)));
287 }
288
289 public void removeNetworkRequest(NetworkRequest networkRequest) {
290 sendMessage(obtainMessage(CMD_CANCEL_REQUEST, networkRequest));
291 }
292
Mathew Inwood55418ea2018-12-20 15:30:45 +0000293 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700294 public void setScoreFilter(int score) {
295 sendMessage(obtainMessage(CMD_SET_SCORE, score, 0));
296 }
297
298 public void setCapabilityFilter(NetworkCapabilities netCap) {
299 sendMessage(obtainMessage(CMD_SET_FILTER, new NetworkCapabilities(netCap)));
300 }
301
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700302 @VisibleForTesting
303 protected int getRequestCount() {
304 return mNetworkRequests.size();
305 }
306
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700307 protected void log(String s) {
308 Log.d(LOG_TAG, s);
309 }
Robert Greenwalt6b746b52014-12-10 14:17:47 -0800310
Mathew Inwood55418ea2018-12-20 15:30:45 +0000311 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Robert Greenwalt3d68dee2015-06-10 20:25:14 -0700312 public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
313 final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ");
314 pw.println(toString());
315 pw.increaseIndent();
316 for (int i = 0; i < mNetworkRequests.size(); i++) {
317 pw.println(mNetworkRequests.valueAt(i));
318 }
319 pw.decreaseIndent();
320 }
321
Robert Greenwalt6b746b52014-12-10 14:17:47 -0800322 @Override
323 public String toString() {
324 StringBuilder sb = new StringBuilder("{").append(LOG_TAG).append(" - ScoreFilter=").
325 append(mScore).append(", Filter=").append(mCapabilityFilter).append(", requests=").
Robert Greenwalt3d68dee2015-06-10 20:25:14 -0700326 append(mNetworkRequests.size()).append(", refCount=").append(mRefCount).
327 append("}");
Robert Greenwalt6b746b52014-12-10 14:17:47 -0800328 return sb.toString();
329 }
Robert Greenwalt3192dec2014-05-27 13:20:24 -0700330}