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 com.android.internal.telephony.dataconnection; 18 19 import android.content.Context; 20 import android.database.ContentObserver; 21 import android.net.ConnectivityManager; 22 import android.net.NetworkCapabilities; 23 import android.net.NetworkFactory; 24 import android.net.NetworkRequest; 25 import android.os.AsyncResult; 26 import android.os.Handler; 27 import android.os.Looper; 28 import android.os.Message; 29 import android.os.Messenger; 30 import android.provider.Settings; 31 import android.telephony.Rlog; 32 import android.telephony.SubscriptionManager; 33 import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener; 34 import android.util.LocalLog; 35 import android.util.SparseArray; 36 37 import com.android.internal.telephony.Phone; 38 import com.android.internal.telephony.PhoneBase; 39 import com.android.internal.telephony.PhoneConstants; 40 import com.android.internal.telephony.PhoneProxy; 41 import com.android.internal.telephony.SubscriptionController; 42 import com.android.internal.telephony.dataconnection.DcSwitchAsyncChannel.RequestInfo; 43 import com.android.internal.util.AsyncChannel; 44 import com.android.internal.util.IndentingPrintWriter; 45 46 import java.io.FileDescriptor; 47 import java.io.PrintWriter; 48 import java.util.ArrayDeque; 49 import java.util.HashMap; 50 import java.util.Iterator; 51 import java.util.Map.Entry; 52 53 public class DctController extends Handler { 54 private static final String LOG_TAG = "DctController"; 55 private static final boolean DBG = true; 56 57 private static final int EVENT_PROCESS_REQUESTS = 100; 58 private static final int EVENT_EXECUTE_REQUEST = 101; 59 private static final int EVENT_EXECUTE_ALL_REQUESTS = 102; 60 private static final int EVENT_RELEASE_REQUEST = 103; 61 private static final int EVENT_RELEASE_ALL_REQUESTS = 104; 62 private static final int EVENT_RETRY_ATTACH = 105; 63 private static final int EVENT_SETTINGS_CHANGED = 106; 64 private static final int EVENT_SUBSCRIPTIONS_CHANGED = 107; 65 66 private static final int EVENT_DATA_ATTACHED = 500; 67 private static final int EVENT_DATA_DETACHED = 600; 68 private static final int EVENT_EMERGENCY_CALL_TOGGLED = 700; 69 70 private static DctController sDctController; 71 72 private int mPhoneNum; 73 private PhoneProxy[] mPhones; 74 private DcSwitchStateMachine[] mDcSwitchStateMachine; 75 private DcSwitchAsyncChannel[] mDcSwitchAsyncChannel; 76 private Handler[] mDcSwitchStateHandler; 77 private HashMap<Integer, RequestInfo> mRequestInfos = new HashMap<Integer, RequestInfo>(); 78 private Context mContext; 79 80 /** Used to send us NetworkRequests from ConnectivityService. Remember it so we can 81 * unregister on dispose. */ 82 private Messenger[] mNetworkFactoryMessenger; 83 private NetworkFactory[] mNetworkFactory; 84 private NetworkCapabilities[] mNetworkFilter; 85 86 private SubscriptionController mSubController = SubscriptionController.getInstance(); 87 88 private SubscriptionManager mSubMgr; 89 90 private OnSubscriptionsChangedListener mOnSubscriptionsChangedListener = 91 new OnSubscriptionsChangedListener() { 92 @Override 93 public void onSubscriptionsChanged() { 94 DctController.this.obtainMessage(EVENT_SUBSCRIPTIONS_CHANGED).sendToTarget(); 95 } 96 }; 97 98 private ContentObserver mObserver = new ContentObserver(new Handler()) { 99 @Override 100 public void onChange(boolean selfChange) { 101 logd("Settings change"); 102 DctController.this.obtainMessage(EVENT_SETTINGS_CHANGED).sendToTarget(); 103 } 104 }; 105 updatePhoneObject(PhoneProxy phone)106 public void updatePhoneObject(PhoneProxy phone) { 107 if (phone == null) { 108 loge("updatePhoneObject phone = null"); 109 return; 110 } 111 112 PhoneBase phoneBase = (PhoneBase)phone.getActivePhone(); 113 if (phoneBase == null) { 114 loge("updatePhoneObject phoneBase = null"); 115 return; 116 } 117 118 for (int i = 0; i < mPhoneNum; i++) { 119 if (mPhones[i] == phone) { 120 updatePhoneBaseForIndex(i, phoneBase); 121 break; 122 } 123 } 124 } 125 updatePhoneBaseForIndex(int index, PhoneBase phoneBase)126 private void updatePhoneBaseForIndex(int index, PhoneBase phoneBase) { 127 logd("updatePhoneBaseForIndex for phone index=" + index); 128 129 phoneBase.getServiceStateTracker().registerForDataConnectionAttached(mRspHandler, 130 EVENT_DATA_ATTACHED + index, null); 131 phoneBase.getServiceStateTracker().registerForDataConnectionDetached(mRspHandler, 132 EVENT_DATA_DETACHED + index, null); 133 phoneBase.registerForEmergencyCallToggle(mRspHandler, 134 EVENT_EMERGENCY_CALL_TOGGLED + index, null); 135 136 ConnectivityManager cm = (ConnectivityManager)mPhones[index].getContext() 137 .getSystemService(Context.CONNECTIVITY_SERVICE); 138 139 if (mNetworkFactoryMessenger != null) { 140 logd("unregister TelephonyNetworkFactory for phone index=" + index); 141 cm.unregisterNetworkFactory(mNetworkFactoryMessenger[index]); 142 mNetworkFactoryMessenger[index] = null; 143 mNetworkFactory[index] = null; 144 mNetworkFilter[index] = null; 145 } 146 147 mNetworkFilter[index] = new NetworkCapabilities(); 148 mNetworkFilter[index].addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR); 149 mNetworkFilter[index].addCapability(NetworkCapabilities.NET_CAPABILITY_MMS); 150 mNetworkFilter[index].addCapability(NetworkCapabilities.NET_CAPABILITY_SUPL); 151 mNetworkFilter[index].addCapability(NetworkCapabilities.NET_CAPABILITY_DUN); 152 mNetworkFilter[index].addCapability(NetworkCapabilities.NET_CAPABILITY_FOTA); 153 mNetworkFilter[index].addCapability(NetworkCapabilities.NET_CAPABILITY_IMS); 154 mNetworkFilter[index].addCapability(NetworkCapabilities.NET_CAPABILITY_CBS); 155 mNetworkFilter[index].addCapability(NetworkCapabilities.NET_CAPABILITY_IA); 156 mNetworkFilter[index].addCapability(NetworkCapabilities.NET_CAPABILITY_RCS); 157 mNetworkFilter[index].addCapability(NetworkCapabilities.NET_CAPABILITY_XCAP); 158 mNetworkFilter[index].addCapability(NetworkCapabilities.NET_CAPABILITY_EIMS); 159 mNetworkFilter[index].addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED); 160 mNetworkFilter[index].addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET); 161 162 mNetworkFactory[index] = new TelephonyNetworkFactory(this.getLooper(), 163 mPhones[index].getContext(), "TelephonyNetworkFactory", phoneBase, 164 mNetworkFilter[index]); 165 mNetworkFactory[index].setScoreFilter(50); 166 mNetworkFactoryMessenger[index] = new Messenger(mNetworkFactory[index]); 167 cm.registerNetworkFactory(mNetworkFactoryMessenger[index], "Telephony"); 168 } 169 170 private Handler mRspHandler = new Handler() { 171 @Override 172 public void handleMessage(Message msg){ 173 if (msg.what >= EVENT_EMERGENCY_CALL_TOGGLED) { 174 logd("EVENT_PHONE" + (msg.what - EVENT_EMERGENCY_CALL_TOGGLED + 1) 175 + "_EMERGENCY_CALL_END."); 176 AsyncResult ar = (AsyncResult) msg.obj; 177 Integer toggle = (Integer) ar.result; 178 mDcSwitchAsyncChannel[msg.what - EVENT_EMERGENCY_CALL_TOGGLED]. 179 notifyEmergencyCallToggled(toggle.intValue()); 180 } else if (msg.what >= EVENT_DATA_DETACHED) { 181 logd("EVENT_PHONE" + (msg.what - EVENT_DATA_DETACHED + 1) 182 + "_DATA_DETACH."); 183 mDcSwitchAsyncChannel[msg.what - EVENT_DATA_DETACHED].notifyDataDetached(); 184 185 } else if (msg.what >= EVENT_DATA_ATTACHED) { 186 logd("EVENT_PHONE" + (msg.what - EVENT_DATA_ATTACHED + 1) 187 + "_DATA_ATTACH."); 188 mDcSwitchAsyncChannel[msg.what - EVENT_DATA_ATTACHED].notifyDataAttached(); 189 } 190 } 191 }; 192 getInstance()193 public static DctController getInstance() { 194 if (sDctController == null) { 195 throw new RuntimeException( 196 "DctController.getInstance can't be called before makeDCTController()"); 197 } 198 return sDctController; 199 } 200 makeDctController(PhoneProxy[] phones)201 public static DctController makeDctController(PhoneProxy[] phones) { 202 if (sDctController == null) { 203 logd("makeDctController: new DctController phones.length=" + phones.length); 204 sDctController = new DctController(phones); 205 } 206 logd("makeDctController: X sDctController=" + sDctController); 207 return sDctController; 208 } 209 DctController(PhoneProxy[] phones)210 private DctController(PhoneProxy[] phones) { 211 logd("DctController(): phones.length=" + phones.length); 212 if (phones == null || phones.length == 0) { 213 if (phones == null) { 214 loge("DctController(phones): UNEXPECTED phones=null, ignore"); 215 } else { 216 loge("DctController(phones): UNEXPECTED phones.length=0, ignore"); 217 } 218 return; 219 } 220 mPhoneNum = phones.length; 221 mPhones = phones; 222 223 mDcSwitchStateMachine = new DcSwitchStateMachine[mPhoneNum]; 224 mDcSwitchAsyncChannel = new DcSwitchAsyncChannel[mPhoneNum]; 225 mDcSwitchStateHandler = new Handler[mPhoneNum]; 226 mNetworkFactoryMessenger = new Messenger[mPhoneNum]; 227 mNetworkFactory = new NetworkFactory[mPhoneNum]; 228 mNetworkFilter = new NetworkCapabilities[mPhoneNum]; 229 230 for (int i = 0; i < mPhoneNum; ++i) { 231 int phoneId = i; 232 mDcSwitchStateMachine[i] = new DcSwitchStateMachine(mPhones[i], 233 "DcSwitchStateMachine-" + phoneId, phoneId); 234 mDcSwitchStateMachine[i].start(); 235 mDcSwitchAsyncChannel[i] = new DcSwitchAsyncChannel(mDcSwitchStateMachine[i], phoneId); 236 mDcSwitchStateHandler[i] = new Handler(); 237 238 int status = mDcSwitchAsyncChannel[i].fullyConnectSync(mPhones[i].getContext(), 239 mDcSwitchStateHandler[i], mDcSwitchStateMachine[i].getHandler()); 240 241 if (status == AsyncChannel.STATUS_SUCCESSFUL) { 242 logd("DctController(phones): Connect success: " + i); 243 } else { 244 loge("DctController(phones): Could not connect to " + i); 245 } 246 247 // Register for radio state change 248 PhoneBase phoneBase = (PhoneBase)mPhones[i].getActivePhone(); 249 updatePhoneBaseForIndex(i, phoneBase); 250 } 251 252 mContext = mPhones[0].getContext(); 253 mSubMgr = SubscriptionManager.from(mContext); 254 mSubMgr.addOnSubscriptionsChangedListener(mOnSubscriptionsChangedListener); 255 256 //Register for settings change. 257 mContext.getContentResolver().registerContentObserver( 258 Settings.Global.getUriFor( 259 Settings.Global.MULTI_SIM_DATA_CALL_SUBSCRIPTION), 260 false, mObserver); 261 } 262 dispose()263 public void dispose() { 264 logd("DctController.dispose"); 265 for (int i = 0; i < mPhoneNum; ++i) { 266 ConnectivityManager cm = (ConnectivityManager)mPhones[i].getContext() 267 .getSystemService(Context.CONNECTIVITY_SERVICE); 268 cm.unregisterNetworkFactory(mNetworkFactoryMessenger[i]); 269 mNetworkFactoryMessenger[i] = null; 270 } 271 272 mSubMgr.removeOnSubscriptionsChangedListener(mOnSubscriptionsChangedListener); 273 mContext.getContentResolver().unregisterContentObserver(mObserver); 274 } 275 276 277 @Override handleMessage(Message msg)278 public void handleMessage (Message msg) { 279 logd("handleMessage msg=" + msg); 280 switch (msg.what) { 281 case EVENT_PROCESS_REQUESTS: 282 onProcessRequest(); 283 break; 284 case EVENT_EXECUTE_REQUEST: 285 onExecuteRequest((RequestInfo)msg.obj); 286 break; 287 case EVENT_EXECUTE_ALL_REQUESTS: 288 onExecuteAllRequests(msg.arg1); 289 break; 290 case EVENT_RELEASE_REQUEST: 291 onReleaseRequest((RequestInfo)msg.obj); 292 break; 293 case EVENT_RELEASE_ALL_REQUESTS: 294 onReleaseAllRequests(msg.arg1); 295 break; 296 case EVENT_RETRY_ATTACH: 297 onRetryAttach(msg.arg1); 298 break; 299 case EVENT_SETTINGS_CHANGED: 300 onSettingsChanged(); 301 break; 302 case EVENT_SUBSCRIPTIONS_CHANGED: 303 onSubInfoReady(); 304 break; 305 default: 306 loge("Un-handled message [" + msg.what + "]"); 307 } 308 } 309 requestNetwork(NetworkRequest request, int priority, LocalLog l, int phoneId)310 private int requestNetwork(NetworkRequest request, int priority, LocalLog l, int phoneId) { 311 logd("requestNetwork request=" + request 312 + ", priority=" + priority); 313 l.log("Dctc.requestNetwork, priority=" + priority); 314 315 RequestInfo requestInfo = new RequestInfo(request, priority, l, phoneId); 316 mRequestInfos.put(request.requestId, requestInfo); 317 processRequests(); 318 319 return PhoneConstants.APN_REQUEST_STARTED; 320 } 321 releaseNetwork(NetworkRequest request)322 private int releaseNetwork(NetworkRequest request) { 323 RequestInfo requestInfo = mRequestInfos.get(request.requestId); 324 logd("releaseNetwork request=" + request + ", requestInfo=" + requestInfo); 325 if (requestInfo != null) requestInfo.log("DctController.releaseNetwork"); 326 327 mRequestInfos.remove(request.requestId); 328 releaseRequest(requestInfo); 329 processRequests(); 330 return PhoneConstants.APN_REQUEST_STARTED; 331 } 332 processRequests()333 void processRequests() { 334 logd("processRequests"); 335 sendMessage(obtainMessage(EVENT_PROCESS_REQUESTS)); 336 } 337 executeRequest(RequestInfo request)338 void executeRequest(RequestInfo request) { 339 logd("executeRequest, request= " + request); 340 sendMessage(obtainMessage(EVENT_EXECUTE_REQUEST, request)); 341 } 342 executeAllRequests(int phoneId)343 void executeAllRequests(int phoneId) { 344 logd("executeAllRequests, phone:" + phoneId); 345 sendMessage(obtainMessage(EVENT_EXECUTE_ALL_REQUESTS, phoneId,0)); 346 } 347 releaseRequest(RequestInfo request)348 void releaseRequest(RequestInfo request) { 349 logd("releaseRequest, request= " + request); 350 sendMessage(obtainMessage(EVENT_RELEASE_REQUEST, request)); 351 } 352 releaseAllRequests(int phoneId)353 void releaseAllRequests(int phoneId) { 354 logd("releaseAllRequests, phone:" + phoneId); 355 sendMessage(obtainMessage(EVENT_RELEASE_ALL_REQUESTS, phoneId, 0)); 356 } 357 retryAttach(int phoneId)358 public void retryAttach(int phoneId) { 359 logd("retryAttach, phone:" + phoneId); 360 sendMessage(obtainMessage(EVENT_RETRY_ATTACH, phoneId, 0)); 361 } 362 onProcessRequest()363 private void onProcessRequest() { 364 //process all requests 365 //1. Check all requests and find subscription of the top priority 366 // request 367 //2. Is current data allowed on the selected subscription 368 //2-1. If yes, execute all the requests of the sub 369 //2-2. If no, set data not allow on the current PS subscription 370 //2-2-1. Set data allow on the selected subscription 371 372 int phoneId = getTopPriorityRequestPhoneId(); 373 int activePhoneId = -1; 374 375 for (int i=0; i<mDcSwitchStateMachine.length; i++) { 376 if (!mDcSwitchAsyncChannel[i].isIdleSync()) { 377 activePhoneId = i; 378 break; 379 } 380 } 381 382 logd("onProcessRequest phoneId=" + phoneId 383 + ", activePhoneId=" + activePhoneId); 384 385 if (activePhoneId == -1 || activePhoneId == phoneId) { 386 Iterator<Integer> iterator = mRequestInfos.keySet().iterator(); 387 while (iterator.hasNext()) { 388 RequestInfo requestInfo = mRequestInfos.get(iterator.next()); 389 if (requestInfo.phoneId == phoneId && !requestInfo.executed) { 390 mDcSwitchAsyncChannel[phoneId].connect(requestInfo); 391 } 392 } 393 } else { 394 mDcSwitchAsyncChannel[activePhoneId].disconnectAll(); 395 } 396 } 397 onExecuteRequest(RequestInfo requestInfo)398 private void onExecuteRequest(RequestInfo requestInfo) { 399 if (!requestInfo.executed && mRequestInfos.containsKey(requestInfo.request.requestId)) { 400 logd("onExecuteRequest request=" + requestInfo); 401 requestInfo.log("DctController.onExecuteRequest - executed=" + requestInfo.executed); 402 requestInfo.executed = true; 403 String apn = apnForNetworkRequest(requestInfo.request); 404 int phoneId = requestInfo.phoneId; 405 PhoneBase phoneBase = (PhoneBase)mPhones[phoneId].getActivePhone(); 406 DcTrackerBase dcTracker = phoneBase.mDcTracker; 407 dcTracker.incApnRefCount(apn, requestInfo.getLog()); 408 } 409 } 410 onExecuteAllRequests(int phoneId)411 private void onExecuteAllRequests(int phoneId) { 412 logd("onExecuteAllRequests phoneId=" + phoneId); 413 Iterator<Integer> iterator = mRequestInfos.keySet().iterator(); 414 while (iterator.hasNext()) { 415 RequestInfo requestInfo = mRequestInfos.get(iterator.next()); 416 if (requestInfo.phoneId == phoneId) { 417 onExecuteRequest(requestInfo); 418 } 419 } 420 } 421 onReleaseRequest(RequestInfo requestInfo)422 private void onReleaseRequest(RequestInfo requestInfo) { 423 logd("onReleaseRequest request=" + requestInfo); 424 if (requestInfo != null) { 425 requestInfo.log("DctController.onReleaseRequest"); 426 if (requestInfo.executed) { 427 String apn = apnForNetworkRequest(requestInfo.request); 428 int phoneId = requestInfo.phoneId; 429 PhoneBase phoneBase = (PhoneBase)mPhones[phoneId].getActivePhone(); 430 DcTrackerBase dcTracker = phoneBase.mDcTracker; 431 dcTracker.decApnRefCount(apn, requestInfo.getLog()); 432 requestInfo.executed = false; 433 } 434 } 435 } 436 onReleaseAllRequests(int phoneId)437 private void onReleaseAllRequests(int phoneId) { 438 logd("onReleaseAllRequests phoneId=" + phoneId); 439 Iterator<Integer> iterator = mRequestInfos.keySet().iterator(); 440 while (iterator.hasNext()) { 441 RequestInfo requestInfo = mRequestInfos.get(iterator.next()); 442 if (requestInfo.phoneId == phoneId) { 443 onReleaseRequest(requestInfo); 444 } 445 } 446 } 447 onRetryAttach(int phoneId)448 private void onRetryAttach(int phoneId) { 449 final int topPriPhone = getTopPriorityRequestPhoneId(); 450 logd("onRetryAttach phoneId=" + phoneId + " topPri phone = " + topPriPhone); 451 452 if (phoneId != -1 && phoneId == topPriPhone) { 453 mDcSwitchAsyncChannel[phoneId].retryConnect(); 454 } 455 } 456 onSettingsChanged()457 private void onSettingsChanged() { 458 //Sub Selection 459 long dataSubId = mSubController.getDefaultDataSubId(); 460 461 int activePhoneId = -1; 462 for (int i=0; i<mDcSwitchStateMachine.length; i++) { 463 if (!mDcSwitchAsyncChannel[i].isIdleSync()) { 464 activePhoneId = i; 465 break; 466 } 467 } 468 469 int[] subIds = SubscriptionManager.getSubId(activePhoneId); 470 if (subIds == null || subIds.length == 0) { 471 loge("onSettingsChange, subIds null or length 0 for activePhoneId " + activePhoneId); 472 return; 473 } 474 logd("onSettingsChange, data sub: " + dataSubId + ", active data sub: " + subIds[0]); 475 476 if (subIds[0] != dataSubId) { 477 Iterator<Integer> iterator = mRequestInfos.keySet().iterator(); 478 while (iterator.hasNext()) { 479 RequestInfo requestInfo = mRequestInfos.get(iterator.next()); 480 String specifier = requestInfo.request.networkCapabilities.getNetworkSpecifier(); 481 if (specifier == null || specifier.equals("")) { 482 if (requestInfo.executed) { 483 String apn = apnForNetworkRequest(requestInfo.request); 484 logd("[setDataSubId] activePhoneId:" + activePhoneId + ", subId =" + 485 dataSubId); 486 requestInfo.log("DctController.onSettingsChange releasing request"); 487 PhoneBase phoneBase = 488 (PhoneBase)mPhones[activePhoneId].getActivePhone(); 489 DcTrackerBase dcTracker = phoneBase.mDcTracker; 490 dcTracker.decApnRefCount(apn, requestInfo.getLog()); 491 requestInfo.executed = false; 492 } 493 } 494 } 495 } 496 497 // Some request maybe pending due to invalid settings 498 // Try to handle pending request when settings changed 499 for (int i = 0; i < mPhoneNum; ++i) { 500 ((DctController.TelephonyNetworkFactory)mNetworkFactory[i]).evalPendingRequest(); 501 } 502 503 processRequests(); 504 } 505 getTopPriorityRequestPhoneId()506 private int getTopPriorityRequestPhoneId() { 507 RequestInfo retRequestInfo = null; 508 int phoneId = 0; 509 int priority = -1; 510 511 //TODO: Handle SIM Switch 512 for (int i=0; i<mPhoneNum; i++) { 513 Iterator<Integer> iterator = mRequestInfos.keySet().iterator(); 514 while (iterator.hasNext()) { 515 RequestInfo requestInfo = mRequestInfos.get(iterator.next()); 516 logd("selectExecPhone requestInfo = " + requestInfo); 517 if (requestInfo.phoneId == i && 518 priority < requestInfo.priority) { 519 priority = requestInfo.priority; 520 retRequestInfo = requestInfo; 521 } 522 } 523 } 524 525 if (retRequestInfo != null) { 526 phoneId = getRequestPhoneId(retRequestInfo.request); 527 } else { 528 int defaultDds = mSubController.getDefaultDataSubId(); 529 phoneId = mSubController.getPhoneId(defaultDds); 530 logd("getTopPriorityRequestPhoneId: RequestInfo list is empty, " + 531 "use Dds sub phone id"); 532 } 533 534 logd("getTopPriorityRequestPhoneId = " + phoneId 535 + ", priority = " + priority); 536 537 return phoneId; 538 } 539 onSubInfoReady()540 private void onSubInfoReady() { 541 logd("onSubInfoReady mPhoneNum=" + mPhoneNum); 542 for (int i = 0; i < mPhoneNum; ++i) { 543 int subId = mPhones[i].getSubId(); 544 logd("onSubInfoReady handle pending requests subId=" + subId); 545 mNetworkFilter[i].setNetworkSpecifier(String.valueOf(subId)); 546 ((DctController.TelephonyNetworkFactory)mNetworkFactory[i]).evalPendingRequest(); 547 } 548 processRequests(); 549 } 550 apnForNetworkRequest(NetworkRequest nr)551 private String apnForNetworkRequest(NetworkRequest nr) { 552 NetworkCapabilities nc = nr.networkCapabilities; 553 // For now, ignore the bandwidth stuff 554 if (nc.getTransportTypes().length > 0 && 555 nc.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) == false) { 556 return null; 557 } 558 559 // in the near term just do 1-1 matches. 560 // TODO - actually try to match the set of capabilities 561 int type = -1; 562 String name = null; 563 564 boolean error = false; 565 if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)) { 566 if (name != null) error = true; 567 name = PhoneConstants.APN_TYPE_DEFAULT; 568 type = ConnectivityManager.TYPE_MOBILE; 569 } 570 if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_MMS)) { 571 if (name != null) error = true; 572 name = PhoneConstants.APN_TYPE_MMS; 573 type = ConnectivityManager.TYPE_MOBILE_MMS; 574 } 575 if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_SUPL)) { 576 if (name != null) error = true; 577 name = PhoneConstants.APN_TYPE_SUPL; 578 type = ConnectivityManager.TYPE_MOBILE_SUPL; 579 } 580 if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_DUN)) { 581 if (name != null) error = true; 582 name = PhoneConstants.APN_TYPE_DUN; 583 type = ConnectivityManager.TYPE_MOBILE_DUN; 584 } 585 if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_FOTA)) { 586 if (name != null) error = true; 587 name = PhoneConstants.APN_TYPE_FOTA; 588 type = ConnectivityManager.TYPE_MOBILE_FOTA; 589 } 590 if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_IMS)) { 591 if (name != null) error = true; 592 name = PhoneConstants.APN_TYPE_IMS; 593 type = ConnectivityManager.TYPE_MOBILE_IMS; 594 } 595 if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_CBS)) { 596 if (name != null) error = true; 597 name = PhoneConstants.APN_TYPE_CBS; 598 type = ConnectivityManager.TYPE_MOBILE_CBS; 599 } 600 if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_IA)) { 601 if (name != null) error = true; 602 name = PhoneConstants.APN_TYPE_IA; 603 type = ConnectivityManager.TYPE_MOBILE_IA; 604 } 605 if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_RCS)) { 606 if (name != null) error = true; 607 name = null; 608 loge("RCS APN type not yet supported"); 609 } 610 if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_XCAP)) { 611 if (name != null) error = true; 612 name = null; 613 loge("XCAP APN type not yet supported"); 614 } 615 if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_EIMS)) { 616 if (name != null) error = true; 617 name = PhoneConstants.APN_TYPE_EMERGENCY; 618 type = ConnectivityManager.TYPE_MOBILE_EMERGENCY; 619 } 620 if (error) { 621 // TODO: If this error condition is removed, the framework's handling of 622 // NET_CAPABILITY_NOT_RESTRICTED will need to be updated so requests for 623 // say FOTA and INTERNET are marked as restricted. This is not how 624 // NetworkCapabilities.maybeMarkCapabilitiesRestricted currently works. 625 loge("Multiple apn types specified in request - result is unspecified!"); 626 } 627 if (type == -1 || name == null) { 628 loge("Unsupported NetworkRequest in Telephony: nr=" + nr); 629 return null; 630 } 631 return name; 632 } 633 getRequestPhoneId(NetworkRequest networkRequest)634 private int getRequestPhoneId(NetworkRequest networkRequest) { 635 String specifier = networkRequest.networkCapabilities.getNetworkSpecifier(); 636 int subId; 637 if (specifier == null || specifier.equals("")) { 638 subId = mSubController.getDefaultDataSubId(); 639 } else { 640 subId = Integer.parseInt(specifier); 641 } 642 int phoneId = mSubController.getPhoneId(subId); 643 if (!SubscriptionManager.isValidPhoneId(phoneId)) { 644 phoneId = 0; 645 if (!SubscriptionManager.isValidPhoneId(phoneId)) { 646 throw new RuntimeException("Should not happen, no valid phoneId"); 647 } 648 } 649 return phoneId; 650 } 651 logd(String s)652 private static void logd(String s) { 653 if (DBG) Rlog.d(LOG_TAG, s); 654 } 655 loge(String s)656 private static void loge(String s) { 657 if (DBG) Rlog.e(LOG_TAG, s); 658 } 659 660 private class TelephonyNetworkFactory extends NetworkFactory { 661 private final SparseArray<NetworkRequest> mPendingReq = new SparseArray<NetworkRequest>(); 662 private Phone mPhone; 663 664 private class RequestLogger { 665 public NetworkRequest request; 666 public LocalLog log; 667 RequestLogger(NetworkRequest r, LocalLog log)668 public RequestLogger(NetworkRequest r, LocalLog log) { 669 request = r; 670 this.log = log; 671 } 672 } 673 674 private static final int MAX_REQUESTS_LOGGED = 20; 675 private static final int MAX_LOG_LINES_PER_REQUEST = 50; 676 677 private ArrayDeque<RequestLogger> mRequestLogs = new ArrayDeque<RequestLogger>(); 678 TelephonyNetworkFactory(Looper l, Context c, String TAG, Phone phone, NetworkCapabilities nc)679 public TelephonyNetworkFactory(Looper l, Context c, String TAG, Phone phone, 680 NetworkCapabilities nc) { 681 super(l, c, TAG, nc); 682 mPhone = phone; 683 log("NetworkCapabilities: " + nc); 684 } 685 requestLog(int requestId, String l)686 public LocalLog requestLog(int requestId, String l) { 687 synchronized(mRequestLogs) { 688 for (RequestLogger r : mRequestLogs) { 689 if (r.request.requestId == requestId) { 690 r.log.log(l); 691 return r.log; 692 } 693 } 694 } 695 return null; 696 } 697 addLogger(NetworkRequest request)698 private LocalLog addLogger(NetworkRequest request) { 699 synchronized(mRequestLogs) { 700 for (RequestLogger r : mRequestLogs) { 701 if (r.request.requestId == request.requestId) { 702 return r.log; 703 } 704 } 705 LocalLog l = new LocalLog(MAX_LOG_LINES_PER_REQUEST); 706 RequestLogger logger = new RequestLogger(request, l); 707 while (mRequestLogs.size() >= MAX_REQUESTS_LOGGED) { 708 mRequestLogs.removeFirst(); 709 } 710 mRequestLogs.addLast(logger); 711 return l; 712 } 713 } 714 715 @Override needNetworkFor(NetworkRequest networkRequest, int score)716 protected void needNetworkFor(NetworkRequest networkRequest, int score) { 717 // figure out the apn type and enable it 718 log("Cellular needs Network for " + networkRequest); 719 720 final LocalLog l = addLogger(networkRequest); 721 722 if (!SubscriptionManager.isUsableSubIdValue(mPhone.getSubId()) || 723 getRequestPhoneId(networkRequest) != mPhone.getPhoneId()) { 724 final String str = "Request not useable, pending request."; 725 log(str); 726 l.log(str); 727 mPendingReq.put(networkRequest.requestId, networkRequest); 728 return; 729 } 730 731 DcTrackerBase dcTracker =((PhoneBase)mPhone).mDcTracker; 732 String apn = apnForNetworkRequest(networkRequest); 733 if (dcTracker.isApnSupported(apn)) { 734 requestNetwork(networkRequest, dcTracker.getApnPriority(apn), l, 735 mPhone.getPhoneId()); 736 } else { 737 final String str = "Unsupported APN"; 738 log(str); 739 l.log(str); 740 } 741 } 742 743 @Override releaseNetworkFor(NetworkRequest networkRequest)744 protected void releaseNetworkFor(NetworkRequest networkRequest) { 745 String str = "Cellular releasing Network for "; 746 log(str + networkRequest); 747 final LocalLog l = requestLog(networkRequest.requestId, str); 748 749 if (mPendingReq.get(networkRequest.requestId) != null) { 750 str = "Sub Info has not been ready, remove request."; 751 log(str); 752 if (l != null) l.log(str); 753 mPendingReq.remove(networkRequest.requestId); 754 return; 755 } 756 757 releaseNetwork(networkRequest); 758 } 759 760 @Override log(String s)761 protected void log(String s) { 762 if (DBG) Rlog.d(LOG_TAG, "[TNF " + mPhone.getSubId() + "]" + s); 763 } 764 evalPendingRequest()765 public void evalPendingRequest() { 766 log("evalPendingRequest, pending request size is " + mPendingReq.size()); 767 int key = 0; 768 for(int i = 0; i < mPendingReq.size(); i++) { 769 key = mPendingReq.keyAt(i); 770 NetworkRequest request = mPendingReq.get(key); 771 log("evalPendingRequest: request = " + request); 772 773 mPendingReq.remove(request.requestId); 774 needNetworkFor(request, 0); 775 } 776 } 777 778 @Override dump(FileDescriptor fd, PrintWriter writer, String[] args)779 public void dump(FileDescriptor fd, PrintWriter writer, String[] args) { 780 super.dump(fd, writer, args); 781 final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " "); 782 pw.increaseIndent(); 783 pw.println("Pending Requests:"); 784 pw.increaseIndent(); 785 for (int i = 0; i < mPendingReq.size(); i++) { 786 NetworkRequest request = mPendingReq.valueAt(i); 787 pw.println(request); 788 } 789 pw.decreaseIndent(); 790 791 pw.println("Request History:"); 792 pw.increaseIndent(); 793 synchronized(mRequestLogs) { 794 for (RequestLogger r : mRequestLogs) { 795 pw.println(r.request); 796 pw.increaseIndent(); 797 r.log.dump(fd, pw, args); 798 pw.decreaseIndent(); 799 } 800 } 801 pw.decreaseIndent(); 802 pw.decreaseIndent(); 803 } 804 } 805 dump(FileDescriptor fd, PrintWriter pw, String[] args)806 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 807 pw.println("DctController:"); 808 try { 809 for (DcSwitchStateMachine dssm : mDcSwitchStateMachine) { 810 dssm.dump(fd, pw, args); 811 } 812 } catch (Exception e) { 813 e.printStackTrace(); 814 } 815 pw.flush(); 816 pw.println("++++++++++++++++++++++++++++++++"); 817 818 try { 819 for (Entry<Integer, RequestInfo> entry : mRequestInfos.entrySet()) { 820 pw.println("mRequestInfos[" + entry.getKey() + "]=" + entry.getValue()); 821 } 822 } catch (Exception e) { 823 e.printStackTrace(); 824 } 825 pw.flush(); 826 pw.println("++++++++++++++++++++++++++++++++"); 827 pw.flush(); 828 pw.println("TelephonyNetworkFactories:"); 829 for (NetworkFactory tnf : mNetworkFactory) { 830 tnf.dump(fd, pw, args); 831 } 832 pw.flush(); 833 pw.println("++++++++++++++++++++++++++++++++"); 834 pw.flush(); 835 } 836 } 837