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 TelephonyNetworkFactory(PhoneSwitcher phoneSwitcher, SubscriptionController subscriptionController, SubscriptionMonitor subscriptionMonitor, Looper looper, Context context, int phoneId, DcTracker dcTracker)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 makeNetworkFilter(SubscriptionController subscriptionController, int phoneId)100 private NetworkCapabilities makeNetworkFilter(SubscriptionController subscriptionController, 101 int phoneId) { 102 final int subscriptionId = subscriptionController.getSubIdUsingPhoneId(phoneId); 103 return makeNetworkFilter(subscriptionId); 104 } 105 makeNetworkFilter(int subscriptionId)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 { InternalHandler(Looper looper)126 public InternalHandler(Looper looper) { 127 super(looper); 128 } 129 130 @Override handleMessage(Message msg)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 applyRequests(HashMap<NetworkRequest, LocalLog> requestMap, boolean action, String logStr)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 onActivePhoneSwitch()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 onSubIdChange()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. onDefaultChange()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 needNetworkFor(NetworkRequest networkRequest, int score)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 onNeedNetworkFor(Message msg)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 releaseNetworkFor(NetworkRequest networkRequest)255 public void releaseNetworkFor(NetworkRequest networkRequest) { 256 Message msg = mInternalHandler.obtainMessage(EVENT_NETWORK_RELEASE); 257 msg.obj = networkRequest; 258 msg.sendToTarget(); 259 } 260 onReleaseNetworkFor(Message msg)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 log(String s)285 protected void log(String s) { 286 Rlog.d(LOG_TAG, s); 287 } 288 dump(FileDescriptor fd, PrintWriter writer, String[] args)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