• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
NetworkFactory(Looper looper, Context context, String logTag, NetworkCapabilities filter)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 
register()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 
unregister()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
handleMessage(Message msg)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 
NetworkRequestInfo(NetworkRequest request, int score)158         public NetworkRequestInfo(NetworkRequest request, int score) {
159             this.request = request;
160             this.score = score;
161             this.requested = false;
162         }
163     }
164 
handleAddRequest(NetworkRequest request, int score)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 
handleRemoveRequest(NetworkRequest request)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 
handleSetScore(int score)188     private void handleSetScore(int score) {
189         mScore = score;
190         evalRequests();
191     }
192 
handleSetFilter(NetworkCapabilities netCap)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      */
acceptRequest(NetworkRequest request, int score)217     public boolean acceptRequest(NetworkRequest request, int score) {
218         return true;
219     }
220 
evalRequest(NetworkRequestInfo n)221     private void evalRequest(NetworkRequestInfo n) {
222         if (VDBG) log("evalRequest");
223         if (n.requested == false && n.score < mScore &&
224                 n.request.networkCapabilities.satisfiedByNetworkCapabilities(
225                 mCapabilityFilter) && acceptRequest(n.request, n.score)) {
226             if (VDBG) log("  needNetworkFor");
227             needNetworkFor(n.request, n.score);
228             n.requested = true;
229         } else if (n.requested == true &&
230                 (n.score > mScore || n.request.networkCapabilities.satisfiedByNetworkCapabilities(
231                 mCapabilityFilter) == false || acceptRequest(n.request, n.score) == false)) {
232             if (VDBG) log("  releaseNetworkFor");
233             releaseNetworkFor(n.request);
234             n.requested = false;
235         } else {
236             if (VDBG) log("  done");
237         }
238     }
239 
evalRequests()240     private void evalRequests() {
241         for (int i = 0; i < mNetworkRequests.size(); i++) {
242             NetworkRequestInfo n = mNetworkRequests.valueAt(i);
243 
244             evalRequest(n);
245         }
246     }
247 
248     // override to do simple mode (request independent)
startNetwork()249     protected void startNetwork() { }
stopNetwork()250     protected void stopNetwork() { }
251 
252     // override to do fancier stuff
needNetworkFor(NetworkRequest networkRequest, int score)253     protected void needNetworkFor(NetworkRequest networkRequest, int score) {
254         if (++mRefCount == 1) startNetwork();
255     }
256 
releaseNetworkFor(NetworkRequest networkRequest)257     protected void releaseNetworkFor(NetworkRequest networkRequest) {
258         if (--mRefCount == 0) stopNetwork();
259     }
260 
261 
addNetworkRequest(NetworkRequest networkRequest, int score)262     public void addNetworkRequest(NetworkRequest networkRequest, int score) {
263         sendMessage(obtainMessage(CMD_REQUEST_NETWORK,
264                 new NetworkRequestInfo(networkRequest, score)));
265     }
266 
removeNetworkRequest(NetworkRequest networkRequest)267     public void removeNetworkRequest(NetworkRequest networkRequest) {
268         sendMessage(obtainMessage(CMD_CANCEL_REQUEST, networkRequest));
269     }
270 
setScoreFilter(int score)271     public void setScoreFilter(int score) {
272         sendMessage(obtainMessage(CMD_SET_SCORE, score, 0));
273     }
274 
setCapabilityFilter(NetworkCapabilities netCap)275     public void setCapabilityFilter(NetworkCapabilities netCap) {
276         sendMessage(obtainMessage(CMD_SET_FILTER, new NetworkCapabilities(netCap)));
277     }
278 
log(String s)279     protected void log(String s) {
280         Log.d(LOG_TAG, s);
281     }
282 
283     @Override
toString()284     public String toString() {
285         StringBuilder sb = new StringBuilder("{").append(LOG_TAG).append(" - ScoreFilter=").
286                 append(mScore).append(", Filter=").append(mCapabilityFilter).append(", requests=").
287                 append(mNetworkRequests.size()).append("}");
288         return sb.toString();
289     }
290 }
291