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