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