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