NetworkFactory.java revision 3192dec32180f56733e631c2d9ec62fa1359283d
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; 27import android.util.SparseArray; 28 29import com.android.internal.util.AsyncChannel; 30import com.android.internal.util.Protocol; 31 32/** 33 * A NetworkFactory is an entity that creates NetworkAgent objects. 34 * The bearers register with ConnectivityService using {@link #register} and 35 * their factory will start receiving scored NetworkRequests. NetworkRequests 36 * can be filtered 3 ways: by NetworkCapabilities, by score and more complexly by 37 * overridden function. All of these can be dynamic - changing NetworkCapabilities 38 * or score forces re-evaluation of all current requests. 39 * 40 * If any requests pass the filter some overrideable functions will be called. 41 * If the bearer only cares about very simple start/stopNetwork callbacks, those 42 * functions can be overridden. If the bearer needs more interaction, it can 43 * override addNetworkRequest and removeNetworkRequest which will give it each 44 * request that passes their current filters. 45 * @hide 46 **/ 47public class NetworkFactory extends Handler { 48 private static final boolean DBG = true; 49 50 private static final int BASE = Protocol.BASE_NETWORK_FACTORY; 51 /** 52 * Pass a network request to the bearer. If the bearer believes it can 53 * satisfy the request it should connect to the network and create a 54 * NetworkAgent. Once the NetworkAgent is fully functional it will 55 * register itself with ConnectivityService using registerNetworkAgent. 56 * If the bearer cannot immediately satisfy the request (no network, 57 * user disabled the radio, lower-scored network) it should remember 58 * any NetworkRequests it may be able to satisfy in the future. It may 59 * disregard any that it will never be able to service, for example 60 * those requiring a different bearer. 61 * msg.obj = NetworkRequest 62 * msg.arg1 = score - the score of the any network currently satisfying this 63 * request. If this bearer knows in advance it cannot 64 * exceed this score it should not try to connect, holding the request 65 * for the future. 66 * Note that subsequent events may give a different (lower 67 * or higher) score for this request, transmitted to each 68 * NetworkFactory through additional CMD_REQUEST_NETWORK msgs 69 * with the same NetworkRequest but an updated score. 70 * Also, network conditions may change for this bearer 71 * allowing for a better score in the future. 72 */ 73 public static final int CMD_REQUEST_NETWORK = BASE; 74 75 /** 76 * Cancel a network request 77 * msg.obj = NetworkRequest 78 */ 79 public static final int CMD_CANCEL_REQUEST = BASE + 1; 80 81 /** 82 * Internally used to set our best-guess score. 83 * msg.arg1 = new score 84 */ 85 private static final int CMD_SET_SCORE = BASE + 2; 86 87 /** 88 * Internally used to set our current filter for coarse bandwidth changes with 89 * technology changes. 90 * msg.obj = new filter 91 */ 92 private static final int CMD_SET_FILTER = BASE + 3; 93 94 private final Context mContext; 95 private final String LOG_TAG; 96 97 private final SparseArray<NetworkRequestInfo> mNetworkRequests = 98 new SparseArray<NetworkRequestInfo>(); 99 100 private int mScore; 101 private NetworkCapabilities mCapabilityFilter; 102 103 private int mRefCount = 0; 104 private Messenger mMessenger = null; 105 106 public NetworkFactory(Looper looper, Context context, String logTag, 107 NetworkCapabilities filter) { 108 super(looper); 109 LOG_TAG = logTag; 110 mContext = context; 111 mCapabilityFilter = filter; 112 } 113 114 public void register() { 115 if (DBG) log("Registering NetworkFactory"); 116 if (mMessenger == null) { 117 mMessenger = new Messenger(this); 118 ConnectivityManager.from(mContext).registerNetworkFactory(mMessenger, LOG_TAG); 119 } 120 } 121 122 public void unregister() { 123 if (DBG) log("Unregistering NetworkFactory"); 124 if (mMessenger != null) { 125 ConnectivityManager.from(mContext).unregisterNetworkFactory(mMessenger); 126 mMessenger = null; 127 } 128 } 129 130 @Override 131 public void handleMessage(Message msg) { 132 switch (msg.what) { 133 case CMD_REQUEST_NETWORK: { 134 handleAddRequest((NetworkRequest)msg.obj, msg.arg1); 135 break; 136 } 137 case CMD_CANCEL_REQUEST: { 138 handleRemoveRequest((NetworkRequest) msg.obj); 139 break; 140 } 141 case CMD_SET_SCORE: { 142 handleSetScore(msg.arg1); 143 break; 144 } 145 case CMD_SET_FILTER: { 146 handleSetFilter((NetworkCapabilities) msg.obj); 147 break; 148 } 149 } 150 } 151 152 private class NetworkRequestInfo { 153 public final NetworkRequest request; 154 public int score; 155 public boolean requested; // do we have a request outstanding, limited by score 156 157 public NetworkRequestInfo(NetworkRequest request, int score) { 158 this.request = request; 159 this.score = score; 160 this.requested = false; 161 } 162 } 163 164 private void handleAddRequest(NetworkRequest request, int score) { 165 NetworkRequestInfo n = mNetworkRequests.get(request.requestId); 166 if (n == null) { 167 n = new NetworkRequestInfo(request, score); 168 mNetworkRequests.put(n.request.requestId, n); 169 } else { 170 n.score = score; 171 } 172 if (DBG) log("got request " + request + " with score " + score); 173 if (DBG) log(" my score=" + mScore + ", my filter=" + mCapabilityFilter); 174 175 evalRequest(n); 176 } 177 178 private void handleRemoveRequest(NetworkRequest request) { 179 NetworkRequestInfo n = mNetworkRequests.get(request.requestId); 180 if (n != null && n.requested) { 181 mNetworkRequests.remove(request.requestId); 182 releaseNetworkFor(n.request); 183 } 184 } 185 186 private void handleSetScore(int score) { 187 mScore = score; 188 evalRequests(); 189 } 190 191 private void handleSetFilter(NetworkCapabilities netCap) { 192 mCapabilityFilter = netCap; 193 evalRequests(); 194 } 195 196 /** 197 * Overridable function to provide complex filtering. 198 * Called for every request every time a new NetworkRequest is seen 199 * and whenever the filterScore or filterNetworkCapabilities change. 200 * 201 * acceptRequest can be overriden to provide complex filter behavior 202 * for the incoming requests 203 * 204 * For output, this class will call {@link #needNetworkFor} and 205 * {@link #releaseNetworkFor} for every request that passes the filters. 206 * If you don't need to see every request, you can leave the base 207 * implementations of those two functions and instead override 208 * {@link #startNetwork} and {@link #stopNetwork}. 209 * 210 * If you want to see every score fluctuation on every request, set 211 * your score filter to a very high number and watch {@link #needNetworkFor}. 212 * 213 * @return {@code true} to accept the request. 214 */ 215 public boolean acceptRequest(NetworkRequest request, int score) { 216 return true; 217 } 218 219 private void evalRequest(NetworkRequestInfo n) { 220 if (n.requested == false && n.score < mScore && 221 n.request.networkCapabilities.satisfiedByNetworkCapabilities( 222 mCapabilityFilter) && acceptRequest(n.request, n.score)) { 223 needNetworkFor(n.request, n.score); 224 n.requested = true; 225 } else if (n.requested == true && 226 (n.score > mScore || n.request.networkCapabilities.satisfiedByNetworkCapabilities( 227 mCapabilityFilter) == false || acceptRequest(n.request, n.score) == false)) { 228 releaseNetworkFor(n.request); 229 n.requested = false; 230 } 231 } 232 233 private void evalRequests() { 234 for (int i = 0; i < mNetworkRequests.size(); i++) { 235 NetworkRequestInfo n = mNetworkRequests.valueAt(i); 236 237 evalRequest(n); 238 } 239 } 240 241 // override to do simple mode (request independent) 242 protected void startNetwork() { } 243 protected void stopNetwork() { } 244 245 // override to do fancier stuff 246 protected void needNetworkFor(NetworkRequest networkRequest, int score) { 247 if (++mRefCount == 1) startNetwork(); 248 } 249 250 protected void releaseNetworkFor(NetworkRequest networkRequest) { 251 if (--mRefCount == 0) stopNetwork(); 252 } 253 254 255 public void addNetworkRequest(NetworkRequest networkRequest, int score) { 256 sendMessage(obtainMessage(CMD_REQUEST_NETWORK, 257 new NetworkRequestInfo(networkRequest, score))); 258 } 259 260 public void removeNetworkRequest(NetworkRequest networkRequest) { 261 sendMessage(obtainMessage(CMD_CANCEL_REQUEST, networkRequest)); 262 } 263 264 public void setScoreFilter(int score) { 265 sendMessage(obtainMessage(CMD_SET_SCORE, score, 0)); 266 } 267 268 public void setCapabilityFilter(NetworkCapabilities netCap) { 269 sendMessage(obtainMessage(CMD_SET_FILTER, new NetworkCapabilities(netCap))); 270 } 271 272 protected void log(String s) { 273 Log.d(LOG_TAG, s); 274 } 275} 276