Home | History | Annotate | Download | only in dataconnection
      1 /*
      2  * Copyright (C) 2016 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 com.android.internal.telephony.dataconnection;
     18 
     19 import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
     20 
     21 import android.content.Context;
     22 import android.net.NetworkCapabilities;
     23 import android.net.NetworkFactory;
     24 import android.net.NetworkRequest;
     25 import android.net.StringNetworkSpecifier;
     26 import android.os.Handler;
     27 import android.os.Looper;
     28 import android.os.Message;
     29 import android.telephony.Rlog;
     30 import android.util.LocalLog;
     31 
     32 import com.android.internal.telephony.PhoneSwitcher;
     33 import com.android.internal.telephony.SubscriptionController;
     34 import com.android.internal.telephony.SubscriptionMonitor;
     35 import com.android.internal.util.IndentingPrintWriter;
     36 
     37 import java.io.FileDescriptor;
     38 import java.io.PrintWriter;
     39 import java.util.HashMap;
     40 
     41 public class TelephonyNetworkFactory extends NetworkFactory {
     42     public final String LOG_TAG;
     43     protected static final boolean DBG = true;
     44 
     45     private final PhoneSwitcher mPhoneSwitcher;
     46     private final SubscriptionController mSubscriptionController;
     47     private final SubscriptionMonitor mSubscriptionMonitor;
     48     private final DcTracker mDcTracker;
     49 
     50     private final HashMap<NetworkRequest, LocalLog> mDefaultRequests =
     51             new HashMap<NetworkRequest, LocalLog>();
     52     private final HashMap<NetworkRequest, LocalLog> mSpecificRequests =
     53             new HashMap<NetworkRequest, LocalLog>();
     54 
     55     private int mPhoneId;
     56     private boolean mIsActive;
     57     private boolean mIsDefault;
     58     private int mSubscriptionId;
     59 
     60     private final static int TELEPHONY_NETWORK_SCORE = 50;
     61 
     62     private final Handler mInternalHandler;
     63     private static final int EVENT_ACTIVE_PHONE_SWITCH          = 1;
     64     private static final int EVENT_SUBSCRIPTION_CHANGED         = 2;
     65     private static final int EVENT_DEFAULT_SUBSCRIPTION_CHANGED = 3;
     66     private static final int EVENT_NETWORK_REQUEST              = 4;
     67     private static final int EVENT_NETWORK_RELEASE              = 5;
     68 
     69     public TelephonyNetworkFactory(PhoneSwitcher phoneSwitcher,
     70             SubscriptionController subscriptionController, SubscriptionMonitor subscriptionMonitor,
     71             Looper looper, Context context, int phoneId, DcTracker dcTracker) {
     72         super(looper, context, "TelephonyNetworkFactory[" + phoneId + "]", null);
     73         mInternalHandler = new InternalHandler(looper);
     74 
     75         setCapabilityFilter(makeNetworkFilter(subscriptionController, phoneId));
     76         setScoreFilter(TELEPHONY_NETWORK_SCORE);
     77 
     78         mPhoneSwitcher = phoneSwitcher;
     79         mSubscriptionController = subscriptionController;
     80         mSubscriptionMonitor = subscriptionMonitor;
     81         mPhoneId = phoneId;
     82         LOG_TAG = "TelephonyNetworkFactory[" + phoneId + "]";
     83         mDcTracker = dcTracker;
     84 
     85         mIsActive = false;
     86         mPhoneSwitcher.registerForActivePhoneSwitch(mPhoneId, mInternalHandler,
     87                 EVENT_ACTIVE_PHONE_SWITCH, null);
     88 
     89         mSubscriptionId = INVALID_SUBSCRIPTION_ID;
     90         mSubscriptionMonitor.registerForSubscriptionChanged(mPhoneId, mInternalHandler,
     91                 EVENT_SUBSCRIPTION_CHANGED, null);
     92 
     93         mIsDefault = false;
     94         mSubscriptionMonitor.registerForDefaultDataSubscriptionChanged(mPhoneId, mInternalHandler,
     95                 EVENT_DEFAULT_SUBSCRIPTION_CHANGED, null);
     96 
     97         register();
     98     }
     99 
    100     private NetworkCapabilities makeNetworkFilter(SubscriptionController subscriptionController,
    101             int phoneId) {
    102         final int subscriptionId = subscriptionController.getSubIdUsingPhoneId(phoneId);
    103         return makeNetworkFilter(subscriptionId);
    104     }
    105 
    106     private NetworkCapabilities makeNetworkFilter(int subscriptionId) {
    107         NetworkCapabilities nc = new NetworkCapabilities();
    108         nc.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
    109         nc.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
    110         nc.addCapability(NetworkCapabilities.NET_CAPABILITY_SUPL);
    111         nc.addCapability(NetworkCapabilities.NET_CAPABILITY_DUN);
    112         nc.addCapability(NetworkCapabilities.NET_CAPABILITY_FOTA);
    113         nc.addCapability(NetworkCapabilities.NET_CAPABILITY_IMS);
    114         nc.addCapability(NetworkCapabilities.NET_CAPABILITY_CBS);
    115         nc.addCapability(NetworkCapabilities.NET_CAPABILITY_IA);
    116         nc.addCapability(NetworkCapabilities.NET_CAPABILITY_RCS);
    117         nc.addCapability(NetworkCapabilities.NET_CAPABILITY_XCAP);
    118         nc.addCapability(NetworkCapabilities.NET_CAPABILITY_EIMS);
    119         nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
    120         nc.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
    121         nc.setNetworkSpecifier(new StringNetworkSpecifier(String.valueOf(subscriptionId)));
    122         return nc;
    123     }
    124 
    125     private class InternalHandler extends Handler {
    126         public InternalHandler(Looper looper) {
    127             super(looper);
    128         }
    129 
    130         @Override
    131         public void handleMessage(Message msg) {
    132             switch (msg.what) {
    133                 case EVENT_ACTIVE_PHONE_SWITCH: {
    134                     onActivePhoneSwitch();
    135                     break;
    136                 }
    137                 case EVENT_SUBSCRIPTION_CHANGED: {
    138                     onSubIdChange();
    139                     break;
    140                 }
    141                 case EVENT_DEFAULT_SUBSCRIPTION_CHANGED: {
    142                     onDefaultChange();
    143                     break;
    144                 }
    145                 case EVENT_NETWORK_REQUEST: {
    146                     onNeedNetworkFor(msg);
    147                     break;
    148                 }
    149                 case EVENT_NETWORK_RELEASE: {
    150                     onReleaseNetworkFor(msg);
    151                     break;
    152                 }
    153             }
    154         }
    155     }
    156 
    157     private static final int REQUEST_LOG_SIZE = 40;
    158     private static final boolean REQUEST = true;
    159     private static final boolean RELEASE = false;
    160 
    161     private void applyRequests(HashMap<NetworkRequest, LocalLog> requestMap, boolean action,
    162             String logStr) {
    163         for (NetworkRequest networkRequest : requestMap.keySet()) {
    164             LocalLog localLog = requestMap.get(networkRequest);
    165             localLog.log(logStr);
    166             if (action == REQUEST) {
    167                 mDcTracker.requestNetwork(networkRequest, localLog);
    168             } else {
    169                 mDcTracker.releaseNetwork(networkRequest, localLog);
    170             }
    171         }
    172     }
    173 
    174     // apply or revoke requests if our active-ness changes
    175     private void onActivePhoneSwitch() {
    176         final boolean newIsActive = mPhoneSwitcher.isPhoneActive(mPhoneId);
    177         if (mIsActive != newIsActive) {
    178             mIsActive = newIsActive;
    179             String logString = "onActivePhoneSwitch(" + mIsActive + ", " + mIsDefault + ")";
    180             if (DBG) log(logString);
    181             if (mIsDefault) {
    182                 applyRequests(mDefaultRequests, (mIsActive ? REQUEST : RELEASE), logString);
    183             }
    184             applyRequests(mSpecificRequests, (mIsActive ? REQUEST : RELEASE), logString);
    185         }
    186     }
    187 
    188     // watch for phone->subId changes, reapply new filter and let
    189     // that flow through to apply/revoke of requests
    190     private void onSubIdChange() {
    191         final int newSubscriptionId = mSubscriptionController.getSubIdUsingPhoneId(mPhoneId);
    192         if (mSubscriptionId != newSubscriptionId) {
    193             if (DBG) log("onSubIdChange " + mSubscriptionId + "->" + newSubscriptionId);
    194             mSubscriptionId = newSubscriptionId;
    195             setCapabilityFilter(makeNetworkFilter(mSubscriptionId));
    196         }
    197     }
    198 
    199     // watch for default-data changes (could be side effect of
    200     // phoneId->subId map change or direct change of default subId)
    201     // and apply/revoke default-only requests.
    202     private void onDefaultChange() {
    203         final int newDefaultSubscriptionId = mSubscriptionController.getDefaultDataSubId();
    204         final boolean newIsDefault = (newDefaultSubscriptionId == mSubscriptionId);
    205         if (newIsDefault != mIsDefault) {
    206             mIsDefault = newIsDefault;
    207             String logString = "onDefaultChange(" + mIsActive + "," + mIsDefault + ")";
    208             if (DBG) log(logString);
    209             if (mIsActive == false) return;
    210             applyRequests(mDefaultRequests, (mIsDefault ? REQUEST : RELEASE), logString);
    211         }
    212     }
    213 
    214     @Override
    215     public void needNetworkFor(NetworkRequest networkRequest, int score) {
    216         Message msg = mInternalHandler.obtainMessage(EVENT_NETWORK_REQUEST);
    217         msg.obj = networkRequest;
    218         msg.sendToTarget();
    219     }
    220 
    221     private void onNeedNetworkFor(Message msg) {
    222         NetworkRequest networkRequest = (NetworkRequest)msg.obj;
    223         boolean isApplicable = false;
    224         LocalLog localLog = null;
    225         if (networkRequest.networkCapabilities.getNetworkSpecifier() == null) {
    226             // request only for the default network
    227             localLog = mDefaultRequests.get(networkRequest);
    228             if (localLog == null) {
    229                 localLog = new LocalLog(REQUEST_LOG_SIZE);
    230                 localLog.log("created for " + networkRequest);
    231                 mDefaultRequests.put(networkRequest, localLog);
    232                 isApplicable = mIsDefault;
    233             }
    234         } else {
    235             localLog = mSpecificRequests.get(networkRequest);
    236             if (localLog == null) {
    237                 localLog = new LocalLog(REQUEST_LOG_SIZE);
    238                 mSpecificRequests.put(networkRequest, localLog);
    239                 isApplicable = true;
    240             }
    241         }
    242         if (mIsActive && isApplicable) {
    243             String s = "onNeedNetworkFor";
    244             localLog.log(s);
    245             log(s + " " + networkRequest);
    246             mDcTracker.requestNetwork(networkRequest, localLog);
    247         } else {
    248             String s = "not acting - isApp=" + isApplicable + ", isAct=" + mIsActive;
    249             localLog.log(s);
    250             log(s + " " + networkRequest);
    251         }
    252     }
    253 
    254     @Override
    255     public void releaseNetworkFor(NetworkRequest networkRequest) {
    256         Message msg = mInternalHandler.obtainMessage(EVENT_NETWORK_RELEASE);
    257         msg.obj = networkRequest;
    258         msg.sendToTarget();
    259     }
    260 
    261     private void onReleaseNetworkFor(Message msg) {
    262         NetworkRequest networkRequest = (NetworkRequest)msg.obj;
    263         LocalLog localLog = null;
    264         boolean isApplicable = false;
    265         if (networkRequest.networkCapabilities.getNetworkSpecifier() == null) {
    266             // request only for the default network
    267             localLog = mDefaultRequests.remove(networkRequest);
    268             isApplicable = (localLog != null) && mIsDefault;
    269         } else {
    270             localLog = mSpecificRequests.remove(networkRequest);
    271             isApplicable = (localLog != null);
    272         }
    273         if (mIsActive && isApplicable) {
    274             String s = "onReleaseNetworkFor";
    275             localLog.log(s);
    276             log(s + " " + networkRequest);
    277             mDcTracker.releaseNetwork(networkRequest, localLog);
    278         } else {
    279             String s = "not releasing - isApp=" + isApplicable + ", isAct=" + mIsActive;
    280             localLog.log(s);
    281             log(s + " " + networkRequest);
    282         }
    283     }
    284 
    285     protected void log(String s) {
    286         Rlog.d(LOG_TAG, s);
    287     }
    288 
    289     public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
    290         final IndentingPrintWriter pw = new IndentingPrintWriter(writer, "  ");
    291         pw.println(LOG_TAG + " mSubId=" + mSubscriptionId + " mIsActive=" +
    292                 mIsActive + " mIsDefault=" + mIsDefault);
    293         pw.println("Default Requests:");
    294         pw.increaseIndent();
    295         for (NetworkRequest nr : mDefaultRequests.keySet()) {
    296             pw.println(nr);
    297             pw.increaseIndent();
    298             mDefaultRequests.get(nr).dump(fd, pw, args);
    299             pw.decreaseIndent();
    300         }
    301         pw.decreaseIndent();
    302     }
    303 }
    304