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