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