1 /* 2 * Copyright 2018 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.text.format.DateUtils.MINUTE_IN_MILLIS; 20 import static android.text.format.DateUtils.SECOND_IN_MILLIS; 21 22 import android.annotation.NonNull; 23 import android.annotation.Nullable; 24 import android.app.AppOpsManager; 25 import android.content.BroadcastReceiver; 26 import android.content.ComponentName; 27 import android.content.Context; 28 import android.content.Intent; 29 import android.content.IntentFilter; 30 import android.content.ServiceConnection; 31 import android.content.pm.PackageManager; 32 import android.content.pm.ResolveInfo; 33 import android.net.LinkProperties; 34 import android.os.AsyncResult; 35 import android.os.Handler; 36 import android.os.IBinder; 37 import android.os.Message; 38 import android.os.PersistableBundle; 39 import android.os.RegistrantList; 40 import android.os.RemoteException; 41 import android.os.UserHandle; 42 import android.permission.LegacyPermissionManager; 43 import android.telephony.AccessNetworkConstants; 44 import android.telephony.AccessNetworkConstants.TransportType; 45 import android.telephony.AnomalyReporter; 46 import android.telephony.CarrierConfigManager; 47 import android.telephony.SubscriptionManager; 48 import android.telephony.data.DataCallResponse; 49 import android.telephony.data.DataProfile; 50 import android.telephony.data.DataService; 51 import android.telephony.data.DataServiceCallback; 52 import android.telephony.data.IDataService; 53 import android.telephony.data.IDataServiceCallback; 54 import android.telephony.data.NetworkSliceInfo; 55 import android.telephony.data.TrafficDescriptor; 56 import android.text.TextUtils; 57 58 import com.android.internal.telephony.Phone; 59 import com.android.internal.telephony.PhoneConfigurationManager; 60 import com.android.internal.telephony.util.TelephonyUtils; 61 import com.android.telephony.Rlog; 62 63 import java.util.HashSet; 64 import java.util.List; 65 import java.util.Map; 66 import java.util.Set; 67 import java.util.UUID; 68 import java.util.concurrent.ConcurrentHashMap; 69 import java.util.concurrent.CountDownLatch; 70 71 /** 72 * Data service manager manages handling data requests and responses on data services (e.g. 73 * Cellular data service, IWLAN data service). 74 */ 75 public class DataServiceManager extends Handler { 76 private static final boolean DBG = true; 77 78 static final String DATA_CALL_RESPONSE = "data_call_response"; 79 80 private static final int EVENT_BIND_DATA_SERVICE = 1; 81 82 private static final int EVENT_WATCHDOG_TIMEOUT = 2; 83 84 private static final long REQUEST_UNRESPONDED_TIMEOUT = 10 * MINUTE_IN_MILLIS; // 10 mins 85 86 private static final long CHANGE_PERMISSION_TIMEOUT_MS = 15 * SECOND_IN_MILLIS; // 15 secs 87 88 private final Phone mPhone; 89 90 private final String mTag; 91 92 private final CarrierConfigManager mCarrierConfigManager; 93 private final AppOpsManager mAppOps; 94 private final LegacyPermissionManager mPermissionManager; 95 96 private final int mTransportType; 97 98 private boolean mBound; 99 100 private IDataService mIDataService; 101 102 private DataServiceManagerDeathRecipient mDeathRecipient; 103 104 private final RegistrantList mServiceBindingChangedRegistrants = new RegistrantList(); 105 106 private final Map<IBinder, Message> mMessageMap = new ConcurrentHashMap<>(); 107 108 private final RegistrantList mDataCallListChangedRegistrants = new RegistrantList(); 109 110 private final RegistrantList mApnUnthrottledRegistrants = new RegistrantList(); 111 112 private String mTargetBindingPackageName; 113 114 private CellularDataServiceConnection mServiceConnection; 115 116 private final UUID mAnomalyUUID = UUID.fromString("fc1956de-c080-45de-8431-a1faab687110"); 117 private String mLastBoundPackageName; 118 119 /** 120 * Helpful for logging 121 * @return the tag name 122 * 123 * @hide 124 */ getTag()125 public String getTag() { 126 return mTag; 127 } 128 129 private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { 130 @Override 131 public void onReceive(Context context, Intent intent) { 132 final String action = intent.getAction(); 133 if (CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED.equals(action) 134 && mPhone.getPhoneId() == intent.getIntExtra( 135 CarrierConfigManager.EXTRA_SLOT_INDEX, 0)) { 136 // We should wait for carrier config changed event because the target binding 137 // package name can come from the carrier config. Note that we still get this event 138 // even when SIM is absent. 139 if (DBG) log("Carrier config changed. Try to bind data service."); 140 sendEmptyMessage(EVENT_BIND_DATA_SERVICE); 141 } 142 } 143 }; 144 145 private class DataServiceManagerDeathRecipient implements IBinder.DeathRecipient { 146 @Override binderDied()147 public void binderDied() { 148 // TODO: try to rebind the service. 149 String message = "Data service " + mLastBoundPackageName + " for transport type " 150 + AccessNetworkConstants.transportTypeToString(mTransportType) + " died."; 151 loge(message); 152 AnomalyReporter.reportAnomaly(mAnomalyUUID, message); 153 } 154 } 155 grantPermissionsToService(String packageName)156 private void grantPermissionsToService(String packageName) { 157 final String[] pkgToGrant = {packageName}; 158 CountDownLatch latch = new CountDownLatch(1); 159 try { 160 mPermissionManager.grantDefaultPermissionsToEnabledTelephonyDataServices( 161 pkgToGrant, UserHandle.of(UserHandle.myUserId()), Runnable::run, 162 isSuccess -> { 163 if (isSuccess) { 164 latch.countDown(); 165 } else { 166 loge("Failed to grant permissions to service."); 167 } 168 }); 169 TelephonyUtils.waitUntilReady(latch, CHANGE_PERMISSION_TIMEOUT_MS); 170 mAppOps.setMode(AppOpsManager.OPSTR_MANAGE_IPSEC_TUNNELS, 171 UserHandle.myUserId(), pkgToGrant[0], AppOpsManager.MODE_ALLOWED); 172 mAppOps.setMode(AppOpsManager.OPSTR_FINE_LOCATION, 173 UserHandle.myUserId(), pkgToGrant[0], AppOpsManager.MODE_ALLOWED); 174 } catch (RuntimeException e) { 175 loge("Binder to package manager died, permission grant for DataService failed."); 176 throw e; 177 } 178 } 179 180 /** 181 * Loop through all DataServices installed on the system and revoke permissions from any that 182 * are not currently the WWAN or WLAN data service. 183 */ revokePermissionsFromUnusedDataServices()184 private void revokePermissionsFromUnusedDataServices() { 185 // Except the current data services from having their permissions removed. 186 Set<String> dataServices = getAllDataServicePackageNames(); 187 for (int transportType : mPhone.getTransportManager().getAvailableTransports()) { 188 dataServices.remove(getDataServicePackageName(transportType)); 189 } 190 191 CountDownLatch latch = new CountDownLatch(1); 192 try { 193 String[] dataServicesArray = new String[dataServices.size()]; 194 dataServices.toArray(dataServicesArray); 195 mPermissionManager.revokeDefaultPermissionsFromDisabledTelephonyDataServices( 196 dataServicesArray, UserHandle.of(UserHandle.myUserId()), Runnable::run, 197 isSuccess -> { 198 if (isSuccess) { 199 latch.countDown(); 200 } else { 201 loge("Failed to revoke permissions from data services."); 202 } 203 }); 204 TelephonyUtils.waitUntilReady(latch, CHANGE_PERMISSION_TIMEOUT_MS); 205 for (String pkg : dataServices) { 206 mAppOps.setMode(AppOpsManager.OPSTR_MANAGE_IPSEC_TUNNELS, UserHandle.myUserId(), 207 pkg, AppOpsManager.MODE_ERRORED); 208 mAppOps.setMode(AppOpsManager.OPSTR_FINE_LOCATION, UserHandle.myUserId(), 209 pkg, AppOpsManager.MODE_ERRORED); 210 } 211 } catch (RuntimeException e) { 212 loge("Binder to package manager died; failed to revoke DataService permissions."); 213 throw e; 214 } 215 } 216 217 private final class CellularDataServiceConnection implements ServiceConnection { 218 @Override onServiceConnected(ComponentName name, IBinder service)219 public void onServiceConnected(ComponentName name, IBinder service) { 220 if (DBG) log("onServiceConnected"); 221 mIDataService = IDataService.Stub.asInterface(service); 222 mDeathRecipient = new DataServiceManagerDeathRecipient(); 223 mBound = true; 224 mLastBoundPackageName = getDataServicePackageName(); 225 removeMessages(EVENT_WATCHDOG_TIMEOUT); 226 227 try { 228 service.linkToDeath(mDeathRecipient, 0); 229 mIDataService.createDataServiceProvider(mPhone.getPhoneId()); 230 mIDataService.registerForDataCallListChanged(mPhone.getPhoneId(), 231 new CellularDataServiceCallback("dataCallListChanged")); 232 mIDataService.registerForUnthrottleApn(mPhone.getPhoneId(), 233 new CellularDataServiceCallback("unthrottleApn")); 234 } catch (RemoteException e) { 235 loge("Remote exception. " + e); 236 return; 237 } 238 mServiceBindingChangedRegistrants.notifyResult(true); 239 } 240 @Override onServiceDisconnected(ComponentName name)241 public void onServiceDisconnected(ComponentName name) { 242 if (DBG) log("onServiceDisconnected"); 243 removeMessages(EVENT_WATCHDOG_TIMEOUT); 244 mIDataService = null; 245 mBound = false; 246 mServiceBindingChangedRegistrants.notifyResult(false); 247 mTargetBindingPackageName = null; 248 } 249 } 250 251 private final class CellularDataServiceCallback extends IDataServiceCallback.Stub { 252 253 private final String mTag; 254 CellularDataServiceCallback(String tag)255 CellularDataServiceCallback(String tag) { 256 mTag = tag; 257 } 258 getTag()259 public String getTag() { 260 return mTag; 261 } 262 263 @Override onSetupDataCallComplete(@ataServiceCallback.ResultCode int resultCode, DataCallResponse response)264 public void onSetupDataCallComplete(@DataServiceCallback.ResultCode int resultCode, 265 DataCallResponse response) { 266 if (DBG) { 267 log("onSetupDataCallComplete. resultCode = " + resultCode + ", response = " 268 + response); 269 } 270 removeMessages(EVENT_WATCHDOG_TIMEOUT, CellularDataServiceCallback.this); 271 Message msg = mMessageMap.remove(asBinder()); 272 if (msg != null) { 273 msg.getData().putParcelable(DATA_CALL_RESPONSE, response); 274 sendCompleteMessage(msg, resultCode); 275 } else { 276 loge("Unable to find the message for setup call response."); 277 } 278 } 279 280 @Override onDeactivateDataCallComplete(@ataServiceCallback.ResultCode int resultCode)281 public void onDeactivateDataCallComplete(@DataServiceCallback.ResultCode int resultCode) { 282 if (DBG) log("onDeactivateDataCallComplete. resultCode = " + resultCode); 283 removeMessages(EVENT_WATCHDOG_TIMEOUT, CellularDataServiceCallback.this); 284 Message msg = mMessageMap.remove(asBinder()); 285 sendCompleteMessage(msg, resultCode); 286 } 287 288 @Override onSetInitialAttachApnComplete(@ataServiceCallback.ResultCode int resultCode)289 public void onSetInitialAttachApnComplete(@DataServiceCallback.ResultCode int resultCode) { 290 if (DBG) log("onSetInitialAttachApnComplete. resultCode = " + resultCode); 291 Message msg = mMessageMap.remove(asBinder()); 292 sendCompleteMessage(msg, resultCode); 293 } 294 295 @Override onSetDataProfileComplete(@ataServiceCallback.ResultCode int resultCode)296 public void onSetDataProfileComplete(@DataServiceCallback.ResultCode int resultCode) { 297 if (DBG) log("onSetDataProfileComplete. resultCode = " + resultCode); 298 Message msg = mMessageMap.remove(asBinder()); 299 sendCompleteMessage(msg, resultCode); 300 } 301 302 @Override onRequestDataCallListComplete(@ataServiceCallback.ResultCode int resultCode, List<DataCallResponse> dataCallList)303 public void onRequestDataCallListComplete(@DataServiceCallback.ResultCode int resultCode, 304 List<DataCallResponse> dataCallList) { 305 if (DBG) log("onRequestDataCallListComplete. resultCode = " + resultCode); 306 Message msg = mMessageMap.remove(asBinder()); 307 sendCompleteMessage(msg, resultCode); 308 } 309 310 @Override onDataCallListChanged(List<DataCallResponse> dataCallList)311 public void onDataCallListChanged(List<DataCallResponse> dataCallList) { 312 mDataCallListChangedRegistrants.notifyRegistrants( 313 new AsyncResult(null, dataCallList, null)); 314 } 315 316 @Override onHandoverStarted(@ataServiceCallback.ResultCode int resultCode)317 public void onHandoverStarted(@DataServiceCallback.ResultCode int resultCode) { 318 if (DBG) log("onHandoverStarted. resultCode = " + resultCode); 319 removeMessages(EVENT_WATCHDOG_TIMEOUT, CellularDataServiceCallback.this); 320 Message msg = mMessageMap.remove(asBinder()); 321 sendCompleteMessage(msg, resultCode); 322 } 323 324 @Override onHandoverCancelled(@ataServiceCallback.ResultCode int resultCode)325 public void onHandoverCancelled(@DataServiceCallback.ResultCode int resultCode) { 326 if (DBG) log("onHandoverCancelled. resultCode = " + resultCode); 327 removeMessages(EVENT_WATCHDOG_TIMEOUT, CellularDataServiceCallback.this); 328 Message msg = mMessageMap.remove(asBinder()); 329 sendCompleteMessage(msg, resultCode); 330 } 331 onApnUnthrottled(String apn)332 public void onApnUnthrottled(String apn) { 333 if (apn != null) { 334 mApnUnthrottledRegistrants.notifyRegistrants( 335 new AsyncResult(null, apn, null)); 336 } else { 337 loge("onApnUnthrottled: apn is null"); 338 } 339 } 340 } 341 342 /** 343 * Constructor 344 * 345 * @param phone The phone object 346 * @param transportType The transport type 347 * @param tagSuffix Logging tag suffix 348 */ DataServiceManager(Phone phone, @TransportType int transportType, String tagSuffix)349 public DataServiceManager(Phone phone, @TransportType int transportType, String tagSuffix) { 350 mPhone = phone; 351 mTag = "DSM" + tagSuffix; 352 mTransportType = transportType; 353 mBound = false; 354 mCarrierConfigManager = (CarrierConfigManager) phone.getContext().getSystemService( 355 Context.CARRIER_CONFIG_SERVICE); 356 // NOTE: Do NOT use AppGlobals to retrieve the permission manager; AppGlobals 357 // caches the service instance, but we need to explicitly request a new service 358 // so it can be mocked out for tests 359 mPermissionManager = (LegacyPermissionManager) phone.getContext().getSystemService( 360 Context.LEGACY_PERMISSION_SERVICE); 361 mAppOps = (AppOpsManager) phone.getContext().getSystemService(Context.APP_OPS_SERVICE); 362 363 IntentFilter intentFilter = new IntentFilter(); 364 intentFilter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED); 365 try { 366 Context contextAsUser = phone.getContext().createPackageContextAsUser( 367 phone.getContext().getPackageName(), 0, UserHandle.ALL); 368 contextAsUser.registerReceiver(mBroadcastReceiver, intentFilter, 369 null /* broadcastPermission */, null); 370 } catch (PackageManager.NameNotFoundException e) { 371 loge("Package name not found: " + e.getMessage()); 372 } 373 PhoneConfigurationManager.registerForMultiSimConfigChange( 374 this, EVENT_BIND_DATA_SERVICE, null); 375 376 sendEmptyMessage(EVENT_BIND_DATA_SERVICE); 377 } 378 379 /** 380 * Handle message events 381 * 382 * @param msg The message to handle 383 */ 384 @Override handleMessage(Message msg)385 public void handleMessage(Message msg) { 386 switch (msg.what) { 387 case EVENT_BIND_DATA_SERVICE: 388 rebindDataService(); 389 break; 390 case EVENT_WATCHDOG_TIMEOUT: 391 handleRequestUnresponded((CellularDataServiceCallback) msg.obj); 392 break; 393 default: 394 loge("Unhandled event " + msg.what); 395 } 396 } 397 handleRequestUnresponded(CellularDataServiceCallback callback)398 private void handleRequestUnresponded(CellularDataServiceCallback callback) { 399 String message = "Request " + callback.getTag() + " unresponded on transport " 400 + AccessNetworkConstants.transportTypeToString(mTransportType) + " in " 401 + REQUEST_UNRESPONDED_TIMEOUT / 1000 + " seconds."; 402 log(message); 403 // Using fixed UUID to avoid duplicate bugreport notification 404 AnomalyReporter.reportAnomaly( 405 UUID.fromString("f5d5cbe6-9bd6-4009-b764-42b1b649b1de"), 406 message); 407 } 408 unbindDataService()409 private void unbindDataService() { 410 // Start by cleaning up all packages that *shouldn't* have permissions. 411 revokePermissionsFromUnusedDataServices(); 412 if (mIDataService != null && mIDataService.asBinder().isBinderAlive()) { 413 log("unbinding service"); 414 // Remove the network availability updater and then unbind the service. 415 try { 416 mIDataService.removeDataServiceProvider(mPhone.getPhoneId()); 417 } catch (RemoteException e) { 418 loge("Cannot remove data service provider. " + e); 419 } 420 } 421 422 if (mServiceConnection != null) { 423 mPhone.getContext().unbindService(mServiceConnection); 424 } 425 mIDataService = null; 426 mServiceConnection = null; 427 mTargetBindingPackageName = null; 428 mBound = false; 429 } 430 bindDataService(String packageName)431 private void bindDataService(String packageName) { 432 if (mPhone == null || !SubscriptionManager.isValidPhoneId(mPhone.getPhoneId())) { 433 loge("can't bindDataService with invalid phone or phoneId."); 434 return; 435 } 436 437 if (TextUtils.isEmpty(packageName)) { 438 loge("Can't find the binding package"); 439 return; 440 } 441 442 Intent intent = null; 443 String className = getDataServiceClassName(); 444 if (TextUtils.isEmpty(className)) { 445 intent = new Intent(DataService.SERVICE_INTERFACE); 446 intent.setPackage(packageName); 447 } else { 448 ComponentName cm = new ComponentName(packageName, className); 449 intent = new Intent(DataService.SERVICE_INTERFACE).setComponent(cm); 450 } 451 452 // Then pre-emptively grant the permissions to the package we will bind. 453 grantPermissionsToService(packageName); 454 455 try { 456 mServiceConnection = new CellularDataServiceConnection(); 457 if (!mPhone.getContext().bindService( 458 intent, mServiceConnection, Context.BIND_AUTO_CREATE)) { 459 loge("Cannot bind to the data service."); 460 return; 461 } 462 mTargetBindingPackageName = packageName; 463 } catch (Exception e) { 464 loge("Cannot bind to the data service. Exception: " + e); 465 } 466 } 467 rebindDataService()468 private void rebindDataService() { 469 String packageName = getDataServicePackageName(); 470 // Do nothing if no need to rebind. 471 if (SubscriptionManager.isValidPhoneId(mPhone.getPhoneId()) 472 && TextUtils.equals(packageName, mTargetBindingPackageName)) { 473 if (DBG) log("Service " + packageName + " already bound or being bound."); 474 return; 475 } 476 477 unbindDataService(); 478 bindDataService(packageName); 479 } 480 481 @NonNull getAllDataServicePackageNames()482 private Set<String> getAllDataServicePackageNames() { 483 // Cowardly using the public PackageManager interface here. 484 // Note: This matches only packages that were installed on the system image. If we ever 485 // expand the permissions model to allow CarrierPrivileged packages, then this will need 486 // to be updated. 487 List<ResolveInfo> dataPackages = 488 mPhone.getContext().getPackageManager().queryIntentServices( 489 new Intent(DataService.SERVICE_INTERFACE), 490 PackageManager.MATCH_SYSTEM_ONLY); 491 HashSet<String> packageNames = new HashSet<>(); 492 for (ResolveInfo info : dataPackages) { 493 if (info.serviceInfo == null) continue; 494 packageNames.add(info.serviceInfo.packageName); 495 } 496 return packageNames; 497 } 498 499 /** 500 * Get the data service package name for our current transport type. 501 * 502 * @return package name of the data service package for the the current transportType. 503 */ getDataServicePackageName()504 public String getDataServicePackageName() { 505 return getDataServicePackageName(mTransportType); 506 } 507 508 /** 509 * Get the data service package by transport type. 510 * 511 * When we bind to a DataService package, we need to revoke permissions from stale 512 * packages; we need to exclude data packages for all transport types, so we need to 513 * to be able to query by transport type. 514 * 515 * @param transportType The transport type 516 * @return package name of the data service package for the specified transportType. 517 */ getDataServicePackageName(@ransportType int transportType)518 private String getDataServicePackageName(@TransportType int transportType) { 519 String packageName; 520 int resourceId; 521 String carrierConfig; 522 523 switch (transportType) { 524 case AccessNetworkConstants.TRANSPORT_TYPE_WWAN: 525 resourceId = com.android.internal.R.string.config_wwan_data_service_package; 526 carrierConfig = CarrierConfigManager 527 .KEY_CARRIER_DATA_SERVICE_WWAN_PACKAGE_OVERRIDE_STRING; 528 break; 529 case AccessNetworkConstants.TRANSPORT_TYPE_WLAN: 530 resourceId = com.android.internal.R.string.config_wlan_data_service_package; 531 carrierConfig = CarrierConfigManager 532 .KEY_CARRIER_DATA_SERVICE_WLAN_PACKAGE_OVERRIDE_STRING; 533 break; 534 default: 535 throw new IllegalStateException("Transport type not WWAN or WLAN. type=" 536 + AccessNetworkConstants.transportTypeToString(mTransportType)); 537 } 538 539 // Read package name from resource overlay 540 packageName = mPhone.getContext().getResources().getString(resourceId); 541 542 PersistableBundle b = mCarrierConfigManager.getConfigForSubId(mPhone.getSubId()); 543 544 if (b != null && !TextUtils.isEmpty(b.getString(carrierConfig))) { 545 // If carrier config overrides it, use the one from carrier config 546 packageName = b.getString(carrierConfig, packageName); 547 } 548 549 return packageName; 550 } 551 552 /** 553 * Get the data service class name for our current transport type. 554 * 555 * @return class name of the data service package for the the current transportType. 556 */ getDataServiceClassName()557 private String getDataServiceClassName() { 558 return getDataServiceClassName(mTransportType); 559 } 560 561 562 /** 563 * Get the data service class by transport type. 564 * 565 * @param transportType either WWAN or WLAN 566 * @return class name of the data service package for the specified transportType. 567 */ getDataServiceClassName(int transportType)568 private String getDataServiceClassName(int transportType) { 569 String className; 570 int resourceId; 571 String carrierConfig; 572 switch (transportType) { 573 case AccessNetworkConstants.TRANSPORT_TYPE_WWAN: 574 resourceId = com.android.internal.R.string.config_wwan_data_service_class; 575 carrierConfig = CarrierConfigManager 576 .KEY_CARRIER_DATA_SERVICE_WWAN_CLASS_OVERRIDE_STRING; 577 break; 578 case AccessNetworkConstants.TRANSPORT_TYPE_WLAN: 579 resourceId = com.android.internal.R.string.config_wlan_data_service_class; 580 carrierConfig = CarrierConfigManager 581 .KEY_CARRIER_DATA_SERVICE_WLAN_CLASS_OVERRIDE_STRING; 582 break; 583 default: 584 throw new IllegalStateException("Transport type not WWAN or WLAN. type=" 585 + transportType); 586 } 587 588 // Read package name from resource overlay 589 className = mPhone.getContext().getResources().getString(resourceId); 590 591 PersistableBundle b = mCarrierConfigManager.getConfigForSubId(mPhone.getSubId()); 592 593 if (b != null && !TextUtils.isEmpty(b.getString(carrierConfig))) { 594 // If carrier config overrides it, use the one from carrier config 595 className = b.getString(carrierConfig, className); 596 } 597 598 return className; 599 } 600 sendCompleteMessage(Message msg, @DataServiceCallback.ResultCode int code)601 private void sendCompleteMessage(Message msg, @DataServiceCallback.ResultCode int code) { 602 if (msg != null) { 603 msg.arg1 = code; 604 msg.sendToTarget(); 605 } 606 } 607 608 /** 609 * Setup a data connection. The data service provider must implement this method to support 610 * establishing a packet data connection. When completed or error, the service must invoke 611 * the provided callback to notify the platform. 612 * 613 * @param accessNetworkType Access network type that the data call will be established on. 614 * Must be one of {@link AccessNetworkConstants.AccessNetworkType}. 615 * @param dataProfile Data profile used for data call setup. See {@link DataProfile} 616 * @param isRoaming True if the device is data roaming. 617 * @param allowRoaming True if data roaming is allowed by the user. 618 * @param reason The reason for data setup. Must be {@link DataService#REQUEST_REASON_NORMAL} or 619 * {@link DataService#REQUEST_REASON_HANDOVER}. 620 * @param linkProperties If {@code reason} is {@link DataService#REQUEST_REASON_HANDOVER}, this 621 * is the link properties of the existing data connection, otherwise null. 622 * @param pduSessionId The pdu session id to be used for this data call. A value of -1 means 623 * no pdu session id was attached to this call. 624 * Reference: 3GPP TS 24.007 Section 11.2.3.1b 625 * @param sliceInfo The slice that represents S-NSSAI. 626 * Reference: 3GPP TS 24.501 627 * @param trafficDescriptor The traffic descriptor for this data call, used for URSP matching. 628 * Reference: 3GPP TS TS 24.526 Section 5.2 629 * @param matchAllRuleAllowed True if using the default match-all URSP rule for this request is 630 * allowed. 631 * @param onCompleteMessage The result message for this request. Null if the client does not 632 * care about the result. 633 */ setupDataCall(int accessNetworkType, DataProfile dataProfile, boolean isRoaming, boolean allowRoaming, int reason, LinkProperties linkProperties, int pduSessionId, @Nullable NetworkSliceInfo sliceInfo, @Nullable TrafficDescriptor trafficDescriptor, boolean matchAllRuleAllowed, Message onCompleteMessage)634 public void setupDataCall(int accessNetworkType, DataProfile dataProfile, boolean isRoaming, 635 boolean allowRoaming, int reason, LinkProperties linkProperties, int pduSessionId, 636 @Nullable NetworkSliceInfo sliceInfo, @Nullable TrafficDescriptor trafficDescriptor, 637 boolean matchAllRuleAllowed, Message onCompleteMessage) { 638 if (DBG) log("setupDataCall"); 639 if (!mBound) { 640 loge("setupDataCall: Data service not bound."); 641 sendCompleteMessage(onCompleteMessage, DataServiceCallback.RESULT_ERROR_ILLEGAL_STATE); 642 return; 643 } 644 645 CellularDataServiceCallback callback = new CellularDataServiceCallback("setupDataCall"); 646 if (onCompleteMessage != null) { 647 mMessageMap.put(callback.asBinder(), onCompleteMessage); 648 } 649 try { 650 sendMessageDelayed(obtainMessage(EVENT_WATCHDOG_TIMEOUT, callback), 651 REQUEST_UNRESPONDED_TIMEOUT); 652 mIDataService.setupDataCall(mPhone.getPhoneId(), accessNetworkType, dataProfile, 653 isRoaming, allowRoaming, reason, linkProperties, pduSessionId, sliceInfo, 654 trafficDescriptor, matchAllRuleAllowed, callback); 655 } catch (RemoteException e) { 656 loge("setupDataCall: Cannot invoke setupDataCall on data service."); 657 mMessageMap.remove(callback.asBinder()); 658 sendCompleteMessage(onCompleteMessage, DataServiceCallback.RESULT_ERROR_ILLEGAL_STATE); 659 } 660 } 661 662 /** 663 * Deactivate a data connection. The data service provider must implement this method to 664 * support data connection tear down. When completed or error, the service must invoke the 665 * provided callback to notify the platform. 666 * 667 * @param cid Call id returned in the callback of {@link #setupDataCall(int, DataProfile, 668 * boolean, boolean, int, LinkProperties, Message)} 669 * @param reason The reason for data deactivation. Must be 670 * {@link DataService#REQUEST_REASON_NORMAL}, {@link DataService#REQUEST_REASON_SHUTDOWN} 671 * or {@link DataService#REQUEST_REASON_HANDOVER}. 672 * @param onCompleteMessage The result message for this request. Null if the client does not 673 * care about the result. 674 */ deactivateDataCall(int cid, int reason, Message onCompleteMessage)675 public void deactivateDataCall(int cid, int reason, Message onCompleteMessage) { 676 if (DBG) log("deactivateDataCall"); 677 if (!mBound) { 678 loge("Data service not bound."); 679 sendCompleteMessage(onCompleteMessage, DataServiceCallback.RESULT_ERROR_ILLEGAL_STATE); 680 return; 681 } 682 683 CellularDataServiceCallback callback = 684 new CellularDataServiceCallback("deactivateDataCall"); 685 if (onCompleteMessage != null) { 686 mMessageMap.put(callback.asBinder(), onCompleteMessage); 687 } 688 try { 689 sendMessageDelayed(obtainMessage(EVENT_WATCHDOG_TIMEOUT, callback), 690 REQUEST_UNRESPONDED_TIMEOUT); 691 mIDataService.deactivateDataCall(mPhone.getPhoneId(), cid, reason, callback); 692 } catch (RemoteException e) { 693 loge("Cannot invoke deactivateDataCall on data service."); 694 mMessageMap.remove(callback.asBinder()); 695 sendCompleteMessage(onCompleteMessage, DataServiceCallback.RESULT_ERROR_ILLEGAL_STATE); 696 } 697 } 698 699 /** 700 * Indicates that a handover has begun. This is called on the source transport. 701 * 702 * Any resources being transferred cannot be released while a 703 * handover is underway. 704 * 705 * If a handover was unsuccessful, then the framework calls DataServiceManager#cancelHandover. 706 * The target transport retains ownership over any of the resources being transferred. 707 * 708 * If a handover was successful, the framework calls DataServiceManager#deactivateDataCall with 709 * reason HANDOVER. The target transport now owns the transferred resources and is 710 * responsible for releasing them. 711 * 712 * @param cid The identifier of the data call which is provided in DataCallResponse 713 * @param onCompleteMessage The result callback for this request. 714 */ startHandover(int cid, @NonNull Message onCompleteMessage)715 public void startHandover(int cid, @NonNull Message onCompleteMessage) { 716 CellularDataServiceCallback callback = 717 setupCallbackHelper("startHandover", onCompleteMessage); 718 if (callback == null) { 719 loge("startHandover: callback == null"); 720 sendCompleteMessage(onCompleteMessage, DataServiceCallback.RESULT_ERROR_ILLEGAL_STATE); 721 return; 722 } 723 724 try { 725 sendMessageDelayed(obtainMessage(EVENT_WATCHDOG_TIMEOUT, callback), 726 REQUEST_UNRESPONDED_TIMEOUT); 727 mIDataService.startHandover(mPhone.getPhoneId(), cid, callback); 728 } catch (RemoteException e) { 729 loge("Cannot invoke startHandover on data service."); 730 mMessageMap.remove(callback.asBinder()); 731 sendCompleteMessage(onCompleteMessage, DataServiceCallback.RESULT_ERROR_ILLEGAL_STATE); 732 } 733 } 734 735 /** 736 * Indicates that a handover was cancelled after a call to DataServiceManager#startHandover. 737 * This is called on the source transport. 738 * 739 * Since the handover was unsuccessful, the source transport retains ownership over any of 740 * the resources being transferred and is still responsible for releasing them. 741 * 742 * @param cid The identifier of the data call which is provided in DataCallResponse 743 * @param onCompleteMessage The result callback for this request. 744 */ cancelHandover(int cid, @NonNull Message onCompleteMessage)745 public void cancelHandover(int cid, @NonNull Message onCompleteMessage) { 746 CellularDataServiceCallback callback = 747 setupCallbackHelper("cancelHandover", onCompleteMessage); 748 if (callback == null) { 749 sendCompleteMessage(onCompleteMessage, DataServiceCallback.RESULT_ERROR_ILLEGAL_STATE); 750 return; 751 } 752 753 try { 754 sendMessageDelayed(obtainMessage(EVENT_WATCHDOG_TIMEOUT, callback), 755 REQUEST_UNRESPONDED_TIMEOUT); 756 mIDataService.cancelHandover(mPhone.getPhoneId(), cid, callback); 757 } catch (RemoteException e) { 758 loge("Cannot invoke cancelHandover on data service."); 759 mMessageMap.remove(callback.asBinder()); 760 sendCompleteMessage(onCompleteMessage, DataServiceCallback.RESULT_ERROR_ILLEGAL_STATE); 761 } 762 } 763 764 @Nullable setupCallbackHelper( @onNull final String operationName, @NonNull final Message onCompleteMessage)765 private CellularDataServiceCallback setupCallbackHelper( 766 @NonNull final String operationName, @NonNull final Message onCompleteMessage) { 767 if (DBG) log(operationName); 768 if (!mBound) { 769 sendCompleteMessage(onCompleteMessage, DataServiceCallback.RESULT_ERROR_ILLEGAL_STATE); 770 return null; 771 } 772 773 CellularDataServiceCallback callback = 774 new CellularDataServiceCallback(operationName); 775 if (onCompleteMessage != null) { 776 if (DBG) log(operationName + ": onCompleteMessage set"); 777 mMessageMap.put(callback.asBinder(), onCompleteMessage); 778 } else { 779 if (DBG) log(operationName + ": onCompleteMessage not set"); 780 } 781 return callback; 782 } 783 784 /** 785 * Set an APN to initial attach network. 786 * 787 * @param dataProfile Data profile used for data call setup. See {@link DataProfile}. 788 * @param isRoaming True if the device is data roaming. 789 * @param onCompleteMessage The result message for this request. Null if the client does not 790 * care about the result. 791 */ setInitialAttachApn(DataProfile dataProfile, boolean isRoaming, Message onCompleteMessage)792 public void setInitialAttachApn(DataProfile dataProfile, boolean isRoaming, 793 Message onCompleteMessage) { 794 if (DBG) log("setInitialAttachApn"); 795 if (!mBound) { 796 loge("Data service not bound."); 797 sendCompleteMessage(onCompleteMessage, DataServiceCallback.RESULT_ERROR_ILLEGAL_STATE); 798 return; 799 } 800 801 CellularDataServiceCallback callback = 802 new CellularDataServiceCallback("setInitialAttachApn"); 803 if (onCompleteMessage != null) { 804 mMessageMap.put(callback.asBinder(), onCompleteMessage); 805 } 806 try { 807 mIDataService.setInitialAttachApn(mPhone.getPhoneId(), dataProfile, isRoaming, 808 callback); 809 } catch (RemoteException e) { 810 loge("Cannot invoke setInitialAttachApn on data service."); 811 mMessageMap.remove(callback.asBinder()); 812 sendCompleteMessage(onCompleteMessage, DataServiceCallback.RESULT_ERROR_ILLEGAL_STATE); 813 } 814 } 815 816 /** 817 * Send current carrier's data profiles to the data service for data call setup. This is 818 * only for CDMA carrier that can change the profile through OTA. The data service should 819 * always uses the latest data profile sent by the framework. 820 * 821 * @param dps A list of data profiles. 822 * @param isRoaming True if the device is data roaming. 823 * @param onCompleteMessage The result message for this request. Null if the client does not 824 * care about the result. 825 */ setDataProfile(List<DataProfile> dps, boolean isRoaming, Message onCompleteMessage)826 public void setDataProfile(List<DataProfile> dps, boolean isRoaming, 827 Message onCompleteMessage) { 828 if (DBG) log("setDataProfile"); 829 if (!mBound) { 830 loge("Data service not bound."); 831 sendCompleteMessage(onCompleteMessage, DataServiceCallback.RESULT_ERROR_ILLEGAL_STATE); 832 return; 833 } 834 835 CellularDataServiceCallback callback = new CellularDataServiceCallback("setDataProfile"); 836 if (onCompleteMessage != null) { 837 mMessageMap.put(callback.asBinder(), onCompleteMessage); 838 } 839 try { 840 mIDataService.setDataProfile(mPhone.getPhoneId(), dps, isRoaming, callback); 841 } catch (RemoteException e) { 842 loge("Cannot invoke setDataProfile on data service."); 843 mMessageMap.remove(callback.asBinder()); 844 sendCompleteMessage(onCompleteMessage, DataServiceCallback.RESULT_ERROR_ILLEGAL_STATE); 845 } 846 } 847 848 /** 849 * Get the active data call list. 850 * 851 * @param onCompleteMessage The result message for this request. Null if the client does not 852 * care about the result. 853 */ requestDataCallList(Message onCompleteMessage)854 public void requestDataCallList(Message onCompleteMessage) { 855 if (DBG) log("requestDataCallList"); 856 if (!mBound) { 857 loge("Data service not bound."); 858 sendCompleteMessage(onCompleteMessage, DataServiceCallback.RESULT_ERROR_ILLEGAL_STATE); 859 return; 860 } 861 862 CellularDataServiceCallback callback = 863 new CellularDataServiceCallback("requestDataCallList"); 864 if (onCompleteMessage != null) { 865 mMessageMap.put(callback.asBinder(), onCompleteMessage); 866 } 867 try { 868 mIDataService.requestDataCallList(mPhone.getPhoneId(), callback); 869 } catch (RemoteException e) { 870 loge("Cannot invoke requestDataCallList on data service."); 871 if (callback != null) { 872 mMessageMap.remove(callback.asBinder()); 873 } 874 sendCompleteMessage(onCompleteMessage, DataServiceCallback.RESULT_ERROR_ILLEGAL_STATE); 875 } 876 } 877 878 /** 879 * Register for data call list changed event. 880 * 881 * @param h The target to post the event message to. 882 * @param what The event. 883 */ registerForDataCallListChanged(Handler h, int what)884 public void registerForDataCallListChanged(Handler h, int what) { 885 if (h != null) { 886 mDataCallListChangedRegistrants.addUnique(h, what, null); 887 } 888 } 889 890 /** 891 * Unregister for data call list changed event. 892 * 893 * @param h The handler 894 */ unregisterForDataCallListChanged(Handler h)895 public void unregisterForDataCallListChanged(Handler h) { 896 if (h != null) { 897 mDataCallListChangedRegistrants.remove(h); 898 } 899 } 900 901 /** 902 * Register apn unthrottled event 903 * 904 * @param h The target to post the event message to. 905 * @param what The event. 906 */ registerForApnUnthrottled(Handler h, int what)907 public void registerForApnUnthrottled(Handler h, int what) { 908 if (h != null) { 909 mApnUnthrottledRegistrants.addUnique(h, what, null); 910 } 911 } 912 913 /** 914 * Unregister for apn unthrottled event 915 * 916 * @param h The handler 917 */ unregisterForApnUnthrottled(Handler h)918 public void unregisterForApnUnthrottled(Handler h) { 919 if (h != null) { 920 mApnUnthrottledRegistrants.remove(h); 921 } 922 } 923 924 /** 925 * Register for data service binding status changed event. 926 * 927 * @param h The target to post the event message to. 928 * @param what The event. 929 * @param obj The user object. 930 */ registerForServiceBindingChanged(Handler h, int what, Object obj)931 public void registerForServiceBindingChanged(Handler h, int what, Object obj) { 932 if (h != null) { 933 mServiceBindingChangedRegistrants.addUnique(h, what, obj); 934 } 935 936 } 937 938 /** 939 * Unregister for data service binding status changed event. 940 * 941 * @param h The handler 942 */ unregisterForServiceBindingChanged(Handler h)943 public void unregisterForServiceBindingChanged(Handler h) { 944 if (h != null) { 945 mServiceBindingChangedRegistrants.remove(h); 946 } 947 } 948 949 /** 950 * Get the transport type. Must be a {@link TransportType}. 951 * 952 * @return 953 */ 954 @TransportType getTransportType()955 public int getTransportType() { 956 return mTransportType; 957 } 958 log(String s)959 private void log(String s) { 960 Rlog.d(mTag, s); 961 } 962 loge(String s)963 private void loge(String s) { 964 Rlog.e(mTag, s); 965 } 966 } 967