Home | History | Annotate | Download | only in net
      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 (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 
    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)
    249     protected void startNetwork() { }
    250     protected void stopNetwork() { }
    251 
    252     // override to do fancier stuff
    253     protected void needNetworkFor(NetworkRequest networkRequest, int score) {
    254         if (++mRefCount == 1) startNetwork();
    255     }
    256 
    257     protected void releaseNetworkFor(NetworkRequest networkRequest) {
    258         if (--mRefCount == 0) stopNetwork();
    259     }
    260 
    261 
    262     public void addNetworkRequest(NetworkRequest networkRequest, int score) {
    263         sendMessage(obtainMessage(CMD_REQUEST_NETWORK,
    264                 new NetworkRequestInfo(networkRequest, score)));
    265     }
    266 
    267     public void removeNetworkRequest(NetworkRequest networkRequest) {
    268         sendMessage(obtainMessage(CMD_CANCEL_REQUEST, networkRequest));
    269     }
    270 
    271     public void setScoreFilter(int score) {
    272         sendMessage(obtainMessage(CMD_SET_SCORE, score, 0));
    273     }
    274 
    275     public void setCapabilityFilter(NetworkCapabilities netCap) {
    276         sendMessage(obtainMessage(CMD_SET_FILTER, new NetworkCapabilities(netCap)));
    277     }
    278 
    279     protected void log(String s) {
    280         Log.d(LOG_TAG, s);
    281     }
    282 
    283     @Override
    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