1 /* 2 * Copyright 2017 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 android.telephony.data; 18 19 import android.annotation.IntDef; 20 import android.annotation.IntRange; 21 import android.annotation.NonNull; 22 import android.annotation.Nullable; 23 import android.annotation.SdkConstant; 24 import android.annotation.SystemApi; 25 import android.app.Service; 26 import android.content.Intent; 27 import android.net.LinkProperties; 28 import android.os.Handler; 29 import android.os.HandlerThread; 30 import android.os.IBinder; 31 import android.os.Looper; 32 import android.os.Message; 33 import android.os.RemoteException; 34 import android.util.Log; 35 import android.util.SparseArray; 36 37 import com.android.internal.annotations.VisibleForTesting; 38 import com.android.telephony.Rlog; 39 40 import java.lang.annotation.Retention; 41 import java.lang.annotation.RetentionPolicy; 42 import java.util.ArrayList; 43 import java.util.List; 44 import java.util.Objects; 45 46 /** 47 * Base class of data service. Services that extend DataService must register the service in 48 * their AndroidManifest to be detected by the framework. They must be protected by the permission 49 * "android.permission.BIND_TELEPHONY_DATA_SERVICE". The data service definition in the manifest 50 * must follow the following format: 51 * ... 52 * <service android:name=".xxxDataService" 53 * android:permission="android.permission.BIND_TELEPHONY_DATA_SERVICE" > 54 * <intent-filter> 55 * <action android:name="android.telephony.data.DataService" /> 56 * </intent-filter> 57 * </service> 58 * @hide 59 */ 60 @SystemApi 61 public abstract class DataService extends Service { 62 private static final String TAG = DataService.class.getSimpleName(); 63 64 @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION) 65 public static final String SERVICE_INTERFACE = "android.telephony.data.DataService"; 66 67 /** {@hide} */ 68 @IntDef(prefix = "REQUEST_REASON_", value = { 69 REQUEST_REASON_UNKNOWN, 70 REQUEST_REASON_NORMAL, 71 REQUEST_REASON_HANDOVER, 72 }) 73 @Retention(RetentionPolicy.SOURCE) 74 public @interface SetupDataReason {} 75 76 /** {@hide} */ 77 @IntDef(prefix = "REQUEST_REASON_", value = { 78 REQUEST_REASON_UNKNOWN, 79 REQUEST_REASON_NORMAL, 80 REQUEST_REASON_SHUTDOWN, 81 REQUEST_REASON_HANDOVER, 82 }) 83 @Retention(RetentionPolicy.SOURCE) 84 public @interface DeactivateDataReason {} 85 86 /** The reason of the data request is unknown */ 87 public static final int REQUEST_REASON_UNKNOWN = 0; 88 89 /** The reason of the data request is normal */ 90 public static final int REQUEST_REASON_NORMAL = 1; 91 92 /** The reason of the data request is device shutdown */ 93 public static final int REQUEST_REASON_SHUTDOWN = 2; 94 95 /** The reason of the data request is IWLAN handover */ 96 public static final int REQUEST_REASON_HANDOVER = 3; 97 98 private static final int DATA_SERVICE_CREATE_DATA_SERVICE_PROVIDER = 1; 99 private static final int DATA_SERVICE_REMOVE_DATA_SERVICE_PROVIDER = 2; 100 private static final int DATA_SERVICE_REMOVE_ALL_DATA_SERVICE_PROVIDERS = 3; 101 private static final int DATA_SERVICE_REQUEST_SETUP_DATA_CALL = 4; 102 private static final int DATA_SERVICE_REQUEST_DEACTIVATE_DATA_CALL = 5; 103 private static final int DATA_SERVICE_REQUEST_SET_INITIAL_ATTACH_APN = 6; 104 private static final int DATA_SERVICE_REQUEST_SET_DATA_PROFILE = 7; 105 private static final int DATA_SERVICE_REQUEST_REQUEST_DATA_CALL_LIST = 8; 106 private static final int DATA_SERVICE_REQUEST_REGISTER_DATA_CALL_LIST_CHANGED = 9; 107 private static final int DATA_SERVICE_REQUEST_UNREGISTER_DATA_CALL_LIST_CHANGED = 10; 108 private static final int DATA_SERVICE_INDICATION_DATA_CALL_LIST_CHANGED = 11; 109 private static final int DATA_SERVICE_REQUEST_START_HANDOVER = 12; 110 private static final int DATA_SERVICE_REQUEST_CANCEL_HANDOVER = 13; 111 private static final int DATA_SERVICE_REQUEST_REGISTER_APN_UNTHROTTLED = 14; 112 private static final int DATA_SERVICE_REQUEST_UNREGISTER_APN_UNTHROTTLED = 15; 113 private static final int DATA_SERVICE_INDICATION_APN_UNTHROTTLED = 16; 114 115 private final HandlerThread mHandlerThread; 116 117 private final DataServiceHandler mHandler; 118 119 private final SparseArray<DataServiceProvider> mServiceMap = new SparseArray<>(); 120 121 /** @hide */ 122 @VisibleForTesting 123 public final IDataServiceWrapper mBinder = new IDataServiceWrapper(); 124 125 /** 126 * The abstract class of the actual data service implementation. The data service provider 127 * must extend this class to support data connection. Note that each instance of data service 128 * provider is associated with one physical SIM slot. 129 */ 130 public abstract class DataServiceProvider implements AutoCloseable { 131 132 private final int mSlotIndex; 133 134 private final List<IDataServiceCallback> mDataCallListChangedCallbacks = new ArrayList<>(); 135 136 private final List<IDataServiceCallback> mApnUnthrottledCallbacks = new ArrayList<>(); 137 138 /** 139 * Constructor 140 * @param slotIndex SIM slot index the data service provider associated with. 141 */ DataServiceProvider(int slotIndex)142 public DataServiceProvider(int slotIndex) { 143 mSlotIndex = slotIndex; 144 } 145 146 /** 147 * @return SIM slot index the data service provider associated with. 148 */ getSlotIndex()149 public final int getSlotIndex() { 150 return mSlotIndex; 151 } 152 153 /** 154 * Setup a data connection. The data service provider must implement this method to support 155 * establishing a packet data connection. When completed or error, the service must invoke 156 * the provided callback to notify the platform. 157 * 158 * @param accessNetworkType Access network type that the data call will be established on. 159 * Must be one of {@link android.telephony.AccessNetworkConstants.AccessNetworkType}. 160 * @param dataProfile Data profile used for data call setup. See {@link DataProfile} 161 * @param isRoaming True if the device is data roaming. 162 * @param allowRoaming True if data roaming is allowed by the user. 163 * @param reason The reason for data setup. Must be {@link #REQUEST_REASON_NORMAL} or 164 * {@link #REQUEST_REASON_HANDOVER}. 165 * @param linkProperties If {@code reason} is {@link #REQUEST_REASON_HANDOVER}, this is the 166 * link properties of the existing data connection, otherwise null. 167 * @param callback The result callback for this request. 168 */ setupDataCall(int accessNetworkType, @NonNull DataProfile dataProfile, boolean isRoaming, boolean allowRoaming, @SetupDataReason int reason, @Nullable LinkProperties linkProperties, @NonNull DataServiceCallback callback)169 public void setupDataCall(int accessNetworkType, @NonNull DataProfile dataProfile, 170 boolean isRoaming, boolean allowRoaming, 171 @SetupDataReason int reason, @Nullable LinkProperties linkProperties, 172 @NonNull DataServiceCallback callback) { 173 // The default implementation is to return unsupported. 174 if (callback != null) { 175 callback.onSetupDataCallComplete(DataServiceCallback.RESULT_ERROR_UNSUPPORTED, 176 null); 177 } 178 } 179 180 /** 181 * Setup a data connection. The data service provider must implement this method to support 182 * establishing a packet data connection. When completed or error, the service must invoke 183 * the provided callback to notify the platform. 184 * 185 * @param accessNetworkType Access network type that the data call will be established on. 186 * Must be one of {@link android.telephony.AccessNetworkConstants.AccessNetworkType}. 187 * @param dataProfile Data profile used for data call setup. See {@link DataProfile} 188 * @param isRoaming True if the device is data roaming. 189 * @param allowRoaming True if data roaming is allowed by the user. 190 * @param reason The reason for data setup. Must be {@link #REQUEST_REASON_NORMAL} or 191 * {@link #REQUEST_REASON_HANDOVER}. 192 * @param linkProperties If {@code reason} is {@link #REQUEST_REASON_HANDOVER}, this is the 193 * link properties of the existing data connection, otherwise null. 194 * @param pduSessionId The pdu session id to be used for this data call. 195 * The standard range of values are 1-15 while 0 means no pdu session id 196 * was attached to this call. Reference: 3GPP TS 24.007 section 197 * 11.2.3.1b. 198 * @param sliceInfo used within the data connection when a handover occurs from EPDG to 5G. 199 * The value is null unless the access network is 200 * {@link android.telephony.AccessNetworkConstants.AccessNetworkType#NGRAN} and a 201 * handover is occurring from EPDG to 5G. If the slice passed is rejected, then 202 * {@link DataCallResponse#getCause()} is 203 * {@link android.telephony.DataFailCause#SLICE_REJECTED}. 204 * @param trafficDescriptor {@link TrafficDescriptor} for which data connection needs to be 205 * established. It is used for URSP traffic matching as described in 3GPP TS 24.526 206 * Section 4.2.2. It includes an optional DNN which, if present, must be used for 207 * traffic matching; it does not specify the end point to be used for the data call. 208 * @param matchAllRuleAllowed Indicates if using default match-all URSP rule for this 209 * request is allowed. If false, this request must not use the match-all URSP rule 210 * and if a non-match-all rule is not found (or if URSP rules are not available) then 211 * {@link DataCallResponse#getCause()} is 212 * {@link android.telephony.DataFailCause#MATCH_ALL_RULE_NOT_ALLOWED}. This is needed 213 * as some requests need to have a hard failure if the intention cannot be met, 214 * for example, a zero-rating slice. 215 * @param callback The result callback for this request. 216 */ setupDataCall(int accessNetworkType, @NonNull DataProfile dataProfile, boolean isRoaming, boolean allowRoaming, @SetupDataReason int reason, @Nullable LinkProperties linkProperties, @IntRange(from = 0, to = 15) int pduSessionId, @Nullable NetworkSliceInfo sliceInfo, @Nullable TrafficDescriptor trafficDescriptor, boolean matchAllRuleAllowed, @NonNull DataServiceCallback callback)217 public void setupDataCall(int accessNetworkType, @NonNull DataProfile dataProfile, 218 boolean isRoaming, boolean allowRoaming, 219 @SetupDataReason int reason, 220 @Nullable LinkProperties linkProperties, 221 @IntRange(from = 0, to = 15) int pduSessionId, @Nullable NetworkSliceInfo sliceInfo, 222 @Nullable TrafficDescriptor trafficDescriptor, boolean matchAllRuleAllowed, 223 @NonNull DataServiceCallback callback) { 224 /* Call the old version since the new version isn't supported */ 225 setupDataCall(accessNetworkType, dataProfile, isRoaming, allowRoaming, reason, 226 linkProperties, callback); 227 } 228 229 /** 230 * Deactivate a data connection. The data service provider must implement this method to 231 * support data connection tear down. When completed or error, the service must invoke the 232 * provided callback to notify the platform. 233 * 234 * @param cid Call id returned in the callback of {@link DataServiceProvider#setupDataCall( 235 * int, DataProfile, boolean, boolean, int, LinkProperties, DataServiceCallback)}. 236 * @param reason The reason for data deactivation. Must be {@link #REQUEST_REASON_NORMAL}, 237 * {@link #REQUEST_REASON_SHUTDOWN} or {@link #REQUEST_REASON_HANDOVER}. 238 * @param callback The result callback for this request. Null if the client does not care 239 * about the result. 240 * 241 */ deactivateDataCall(int cid, @DeactivateDataReason int reason, @Nullable DataServiceCallback callback)242 public void deactivateDataCall(int cid, @DeactivateDataReason int reason, 243 @Nullable DataServiceCallback callback) { 244 // The default implementation is to return unsupported. 245 if (callback != null) { 246 callback.onDeactivateDataCallComplete(DataServiceCallback.RESULT_ERROR_UNSUPPORTED); 247 } 248 } 249 250 /** 251 * Set an APN to initial attach network. 252 * 253 * @param dataProfile Data profile used for data call setup. See {@link DataProfile}. 254 * @param isRoaming True if the device is data roaming. 255 * @param callback The result callback for this request. 256 */ setInitialAttachApn(@onNull DataProfile dataProfile, boolean isRoaming, @NonNull DataServiceCallback callback)257 public void setInitialAttachApn(@NonNull DataProfile dataProfile, boolean isRoaming, 258 @NonNull DataServiceCallback callback) { 259 // The default implementation is to return unsupported. 260 if (callback != null) { 261 callback.onSetInitialAttachApnComplete( 262 DataServiceCallback.RESULT_ERROR_UNSUPPORTED); 263 } 264 } 265 266 /** 267 * Send current carrier's data profiles to the data service for data call setup. This is 268 * only for CDMA carrier that can change the profile through OTA. The data service should 269 * always uses the latest data profile sent by the framework. 270 * 271 * @param dps A list of data profiles. 272 * @param isRoaming True if the device is data roaming. 273 * @param callback The result callback for this request. 274 */ setDataProfile(@onNull List<DataProfile> dps, boolean isRoaming, @NonNull DataServiceCallback callback)275 public void setDataProfile(@NonNull List<DataProfile> dps, boolean isRoaming, 276 @NonNull DataServiceCallback callback) { 277 // The default implementation is to return unsupported. 278 if (callback != null) { 279 callback.onSetDataProfileComplete(DataServiceCallback.RESULT_ERROR_UNSUPPORTED); 280 } 281 } 282 283 /** 284 * Indicates that a handover has begun. This is called on the source transport. 285 * 286 * Any resources being transferred cannot be released while a 287 * handover is underway. 288 * <p/> 289 * If a handover was unsuccessful, then the framework calls 290 * {@link DataService#cancelHandover}. The target transport retains ownership over any of 291 * the resources being transferred. 292 * <p/> 293 * If a handover was successful, the framework calls {@link DataService#deactivateDataCall} 294 * with reason {@link DataService.REQUEST_REASON_HANDOVER}. The target transport now owns 295 * the transferred resources and is responsible for releasing them. 296 * 297 * @param cid The identifier of the data call which is provided in {@link DataCallResponse} 298 * @param callback The result callback for this request. 299 * 300 * @hide 301 */ startHandover(int cid, @NonNull DataServiceCallback callback)302 public void startHandover(int cid, @NonNull DataServiceCallback callback) { 303 Objects.requireNonNull(callback, "callback cannot be null"); 304 // The default implementation is to return unsupported. 305 Log.d(TAG, "startHandover: " + cid); 306 callback.onHandoverStarted(DataServiceCallback.RESULT_ERROR_UNSUPPORTED); 307 } 308 309 /** 310 * Indicates that a handover was cancelled after a call to 311 * {@link DataService#startHandover}. This is called on the source transport. 312 * <p/> 313 * Since the handover was unsuccessful, the source transport retains ownership over any of 314 * the resources being transferred and is still responsible for releasing them. 315 * <p/> 316 * The handover can be cancelled up until either: 317 * <ul><li> 318 * The handover was successful after receiving a successful response from 319 * {@link DataService#setupDataCall} on the target transport. 320 * </li><li> 321 * The data call on the source transport was lost. 322 * </li> 323 * </ul> 324 * 325 * @param cid The identifier of the data call which is provided in {@link DataCallResponse} 326 * @param callback The result callback for this request. 327 * 328 * @hide 329 */ cancelHandover(int cid, @NonNull DataServiceCallback callback)330 public void cancelHandover(int cid, @NonNull DataServiceCallback callback) { 331 Objects.requireNonNull(callback, "callback cannot be null"); 332 // The default implementation is to return unsupported. 333 Log.d(TAG, "cancelHandover: " + cid); 334 callback.onHandoverCancelled(DataServiceCallback.RESULT_ERROR_UNSUPPORTED); 335 } 336 337 /** 338 * Get the active data call list. 339 * 340 * @param callback The result callback for this request. 341 */ requestDataCallList(@onNull DataServiceCallback callback)342 public void requestDataCallList(@NonNull DataServiceCallback callback) { 343 // The default implementation is to return unsupported. 344 callback.onRequestDataCallListComplete(DataServiceCallback.RESULT_ERROR_UNSUPPORTED, 345 null); 346 } 347 registerForDataCallListChanged(IDataServiceCallback callback)348 private void registerForDataCallListChanged(IDataServiceCallback callback) { 349 synchronized (mDataCallListChangedCallbacks) { 350 mDataCallListChangedCallbacks.add(callback); 351 } 352 } 353 unregisterForDataCallListChanged(IDataServiceCallback callback)354 private void unregisterForDataCallListChanged(IDataServiceCallback callback) { 355 synchronized (mDataCallListChangedCallbacks) { 356 mDataCallListChangedCallbacks.remove(callback); 357 } 358 } 359 registerForApnUnthrottled(IDataServiceCallback callback)360 private void registerForApnUnthrottled(IDataServiceCallback callback) { 361 synchronized (mApnUnthrottledCallbacks) { 362 mApnUnthrottledCallbacks.add(callback); 363 } 364 } 365 unregisterForApnUnthrottled(IDataServiceCallback callback)366 private void unregisterForApnUnthrottled(IDataServiceCallback callback) { 367 synchronized (mApnUnthrottledCallbacks) { 368 mApnUnthrottledCallbacks.remove(callback); 369 } 370 } 371 372 373 /** 374 * Notify the system that current data call list changed. Data service must invoke this 375 * method whenever there is any data call status changed. 376 * 377 * @param dataCallList List of the current active data call. 378 */ notifyDataCallListChanged(List<DataCallResponse> dataCallList)379 public final void notifyDataCallListChanged(List<DataCallResponse> dataCallList) { 380 synchronized (mDataCallListChangedCallbacks) { 381 for (IDataServiceCallback callback : mDataCallListChangedCallbacks) { 382 mHandler.obtainMessage(DATA_SERVICE_INDICATION_DATA_CALL_LIST_CHANGED, 383 mSlotIndex, 0, new DataCallListChangedIndication(dataCallList, 384 callback)).sendToTarget(); 385 } 386 } 387 } 388 389 /** 390 * Notify the system that a given APN was unthrottled. 391 * 392 * @param apn Access Point Name defined by the carrier. 393 */ notifyApnUnthrottled(@onNull String apn)394 public final void notifyApnUnthrottled(@NonNull String apn) { 395 synchronized (mApnUnthrottledCallbacks) { 396 for (IDataServiceCallback callback : mApnUnthrottledCallbacks) { 397 mHandler.obtainMessage(DATA_SERVICE_INDICATION_APN_UNTHROTTLED, 398 mSlotIndex, 0, new ApnUnthrottledIndication(apn, 399 callback)).sendToTarget(); 400 } 401 } 402 } 403 404 /** 405 * Called when the instance of data service is destroyed (e.g. got unbind or binder died) 406 * or when the data service provider is removed. The extended class should implement this 407 * method to perform cleanup works. 408 */ 409 @Override close()410 public abstract void close(); 411 } 412 413 private static final class SetupDataCallRequest { 414 public final int accessNetworkType; 415 public final DataProfile dataProfile; 416 public final boolean isRoaming; 417 public final boolean allowRoaming; 418 public final int reason; 419 public final LinkProperties linkProperties; 420 public final int pduSessionId; 421 public final NetworkSliceInfo sliceInfo; 422 public final TrafficDescriptor trafficDescriptor; 423 public final boolean matchAllRuleAllowed; 424 public final IDataServiceCallback callback; SetupDataCallRequest(int accessNetworkType, DataProfile dataProfile, boolean isRoaming, boolean allowRoaming, int reason, LinkProperties linkProperties, int pduSessionId, NetworkSliceInfo sliceInfo, TrafficDescriptor trafficDescriptor, boolean matchAllRuleAllowed, IDataServiceCallback callback)425 SetupDataCallRequest(int accessNetworkType, DataProfile dataProfile, boolean isRoaming, 426 boolean allowRoaming, int reason, LinkProperties linkProperties, int pduSessionId, 427 NetworkSliceInfo sliceInfo, TrafficDescriptor trafficDescriptor, 428 boolean matchAllRuleAllowed, IDataServiceCallback callback) { 429 this.accessNetworkType = accessNetworkType; 430 this.dataProfile = dataProfile; 431 this.isRoaming = isRoaming; 432 this.allowRoaming = allowRoaming; 433 this.linkProperties = linkProperties; 434 this.reason = reason; 435 this.pduSessionId = pduSessionId; 436 this.sliceInfo = sliceInfo; 437 this.trafficDescriptor = trafficDescriptor; 438 this.matchAllRuleAllowed = matchAllRuleAllowed; 439 this.callback = callback; 440 } 441 } 442 443 private static final class DeactivateDataCallRequest { 444 public final int cid; 445 public final int reason; 446 public final IDataServiceCallback callback; DeactivateDataCallRequest(int cid, int reason, IDataServiceCallback callback)447 DeactivateDataCallRequest(int cid, int reason, IDataServiceCallback callback) { 448 this.cid = cid; 449 this.reason = reason; 450 this.callback = callback; 451 } 452 } 453 454 private static final class SetInitialAttachApnRequest { 455 public final DataProfile dataProfile; 456 public final boolean isRoaming; 457 public final IDataServiceCallback callback; SetInitialAttachApnRequest(DataProfile dataProfile, boolean isRoaming, IDataServiceCallback callback)458 SetInitialAttachApnRequest(DataProfile dataProfile, boolean isRoaming, 459 IDataServiceCallback callback) { 460 this.dataProfile = dataProfile; 461 this.isRoaming = isRoaming; 462 this.callback = callback; 463 } 464 } 465 466 private static final class SetDataProfileRequest { 467 public final List<DataProfile> dps; 468 public final boolean isRoaming; 469 public final IDataServiceCallback callback; SetDataProfileRequest(List<DataProfile> dps, boolean isRoaming, IDataServiceCallback callback)470 SetDataProfileRequest(List<DataProfile> dps, boolean isRoaming, 471 IDataServiceCallback callback) { 472 this.dps = dps; 473 this.isRoaming = isRoaming; 474 this.callback = callback; 475 } 476 } 477 478 private static final class BeginCancelHandoverRequest { 479 public final int cid; 480 public final IDataServiceCallback callback; BeginCancelHandoverRequest(int cid, IDataServiceCallback callback)481 BeginCancelHandoverRequest(int cid, 482 IDataServiceCallback callback) { 483 this.cid = cid; 484 this.callback = callback; 485 } 486 } 487 488 private static final class DataCallListChangedIndication { 489 public final List<DataCallResponse> dataCallList; 490 public final IDataServiceCallback callback; DataCallListChangedIndication(List<DataCallResponse> dataCallList, IDataServiceCallback callback)491 DataCallListChangedIndication(List<DataCallResponse> dataCallList, 492 IDataServiceCallback callback) { 493 this.dataCallList = dataCallList; 494 this.callback = callback; 495 } 496 } 497 498 private static final class ApnUnthrottledIndication { 499 public final String apn; 500 public final IDataServiceCallback callback; ApnUnthrottledIndication(String apn, IDataServiceCallback callback)501 ApnUnthrottledIndication(String apn, 502 IDataServiceCallback callback) { 503 this.apn = apn; 504 this.callback = callback; 505 } 506 } 507 508 private class DataServiceHandler extends Handler { 509 DataServiceHandler(Looper looper)510 DataServiceHandler(Looper looper) { 511 super(looper); 512 } 513 514 @Override handleMessage(Message message)515 public void handleMessage(Message message) { 516 IDataServiceCallback callback; 517 final int slotIndex = message.arg1; 518 DataServiceProvider serviceProvider = mServiceMap.get(slotIndex); 519 520 switch (message.what) { 521 case DATA_SERVICE_CREATE_DATA_SERVICE_PROVIDER: 522 serviceProvider = onCreateDataServiceProvider(message.arg1); 523 if (serviceProvider != null) { 524 mServiceMap.put(slotIndex, serviceProvider); 525 } 526 break; 527 case DATA_SERVICE_REMOVE_DATA_SERVICE_PROVIDER: 528 if (serviceProvider != null) { 529 serviceProvider.close(); 530 mServiceMap.remove(slotIndex); 531 } 532 break; 533 case DATA_SERVICE_REMOVE_ALL_DATA_SERVICE_PROVIDERS: 534 for (int i = 0; i < mServiceMap.size(); i++) { 535 serviceProvider = mServiceMap.get(i); 536 if (serviceProvider != null) { 537 serviceProvider.close(); 538 } 539 } 540 mServiceMap.clear(); 541 break; 542 case DATA_SERVICE_REQUEST_SETUP_DATA_CALL: 543 if (serviceProvider == null) break; 544 SetupDataCallRequest setupDataCallRequest = (SetupDataCallRequest) message.obj; 545 serviceProvider.setupDataCall(setupDataCallRequest.accessNetworkType, 546 setupDataCallRequest.dataProfile, setupDataCallRequest.isRoaming, 547 setupDataCallRequest.allowRoaming, setupDataCallRequest.reason, 548 setupDataCallRequest.linkProperties, setupDataCallRequest.pduSessionId, 549 setupDataCallRequest.sliceInfo, setupDataCallRequest.trafficDescriptor, 550 setupDataCallRequest.matchAllRuleAllowed, 551 (setupDataCallRequest.callback != null) 552 ? new DataServiceCallback(setupDataCallRequest.callback) 553 : null); 554 555 break; 556 case DATA_SERVICE_REQUEST_DEACTIVATE_DATA_CALL: 557 if (serviceProvider == null) break; 558 DeactivateDataCallRequest deactivateDataCallRequest = 559 (DeactivateDataCallRequest) message.obj; 560 serviceProvider.deactivateDataCall(deactivateDataCallRequest.cid, 561 deactivateDataCallRequest.reason, 562 (deactivateDataCallRequest.callback != null) 563 ? new DataServiceCallback(deactivateDataCallRequest.callback) 564 : null); 565 break; 566 case DATA_SERVICE_REQUEST_SET_INITIAL_ATTACH_APN: 567 if (serviceProvider == null) break; 568 SetInitialAttachApnRequest setInitialAttachApnRequest = 569 (SetInitialAttachApnRequest) message.obj; 570 serviceProvider.setInitialAttachApn(setInitialAttachApnRequest.dataProfile, 571 setInitialAttachApnRequest.isRoaming, 572 (setInitialAttachApnRequest.callback != null) 573 ? new DataServiceCallback(setInitialAttachApnRequest.callback) 574 : null); 575 break; 576 case DATA_SERVICE_REQUEST_SET_DATA_PROFILE: 577 if (serviceProvider == null) break; 578 SetDataProfileRequest setDataProfileRequest = 579 (SetDataProfileRequest) message.obj; 580 serviceProvider.setDataProfile(setDataProfileRequest.dps, 581 setDataProfileRequest.isRoaming, 582 (setDataProfileRequest.callback != null) 583 ? new DataServiceCallback(setDataProfileRequest.callback) 584 : null); 585 break; 586 case DATA_SERVICE_REQUEST_REQUEST_DATA_CALL_LIST: 587 if (serviceProvider == null) break; 588 589 serviceProvider.requestDataCallList(new DataServiceCallback( 590 (IDataServiceCallback) message.obj)); 591 break; 592 case DATA_SERVICE_REQUEST_REGISTER_DATA_CALL_LIST_CHANGED: 593 if (serviceProvider == null) break; 594 serviceProvider.registerForDataCallListChanged((IDataServiceCallback) message.obj); 595 break; 596 case DATA_SERVICE_REQUEST_UNREGISTER_DATA_CALL_LIST_CHANGED: 597 if (serviceProvider == null) break; 598 callback = (IDataServiceCallback) message.obj; 599 serviceProvider.unregisterForDataCallListChanged(callback); 600 break; 601 case DATA_SERVICE_INDICATION_DATA_CALL_LIST_CHANGED: 602 if (serviceProvider == null) break; 603 DataCallListChangedIndication indication = 604 (DataCallListChangedIndication) message.obj; 605 try { 606 indication.callback.onDataCallListChanged(indication.dataCallList); 607 } catch (RemoteException e) { 608 loge("Failed to call onDataCallListChanged. " + e); 609 } 610 break; 611 case DATA_SERVICE_REQUEST_START_HANDOVER: 612 if (serviceProvider == null) break; 613 BeginCancelHandoverRequest bReq = (BeginCancelHandoverRequest) message.obj; 614 serviceProvider.startHandover(bReq.cid, 615 (bReq.callback != null) 616 ? new DataServiceCallback(bReq.callback) : null); 617 break; 618 case DATA_SERVICE_REQUEST_CANCEL_HANDOVER: 619 if (serviceProvider == null) break; 620 BeginCancelHandoverRequest cReq = (BeginCancelHandoverRequest) message.obj; 621 serviceProvider.cancelHandover(cReq.cid, 622 (cReq.callback != null) 623 ? new DataServiceCallback(cReq.callback) : null); 624 break; 625 case DATA_SERVICE_REQUEST_REGISTER_APN_UNTHROTTLED: 626 if (serviceProvider == null) break; 627 serviceProvider.registerForApnUnthrottled((IDataServiceCallback) message.obj); 628 break; 629 case DATA_SERVICE_REQUEST_UNREGISTER_APN_UNTHROTTLED: 630 if (serviceProvider == null) break; 631 callback = (IDataServiceCallback) message.obj; 632 serviceProvider.unregisterForApnUnthrottled(callback); 633 break; 634 case DATA_SERVICE_INDICATION_APN_UNTHROTTLED: 635 if (serviceProvider == null) break; 636 ApnUnthrottledIndication apnUnthrottledIndication = 637 (ApnUnthrottledIndication) message.obj; 638 try { 639 apnUnthrottledIndication.callback 640 .onApnUnthrottled(apnUnthrottledIndication.apn); 641 } catch (RemoteException e) { 642 loge("Failed to call onApnUnthrottled. " + e); 643 } 644 break; 645 } 646 } 647 } 648 649 /** 650 * Default constructor. 651 */ DataService()652 public DataService() { 653 mHandlerThread = new HandlerThread(TAG); 654 mHandlerThread.start(); 655 656 mHandler = new DataServiceHandler(mHandlerThread.getLooper()); 657 log("Data service created"); 658 } 659 660 /** 661 * Create the instance of {@link DataServiceProvider}. Data service provider must override 662 * this method to facilitate the creation of {@link DataServiceProvider} instances. The system 663 * will call this method after binding the data service for each active SIM slot id. 664 * 665 * This methead is guaranteed to be invoked in {@link DataService}'s internal handler thread 666 * whose looper can be retrieved with {@link Looper.myLooper()} when override this method. 667 * 668 * @param slotIndex SIM slot id the data service associated with. 669 * @return Data service object. Null if failed to create the provider (e.g. invalid slot index) 670 */ 671 @Nullable onCreateDataServiceProvider(int slotIndex)672 public abstract DataServiceProvider onCreateDataServiceProvider(int slotIndex); 673 674 @Override onBind(Intent intent)675 public IBinder onBind(Intent intent) { 676 if (intent == null || !SERVICE_INTERFACE.equals(intent.getAction())) { 677 loge("Unexpected intent " + intent); 678 return null; 679 } 680 return mBinder; 681 } 682 683 @Override onUnbind(Intent intent)684 public boolean onUnbind(Intent intent) { 685 mHandler.obtainMessage(DATA_SERVICE_REMOVE_ALL_DATA_SERVICE_PROVIDERS).sendToTarget(); 686 return false; 687 } 688 689 @Override onDestroy()690 public void onDestroy() { 691 mHandlerThread.quit(); 692 super.onDestroy(); 693 } 694 695 /** 696 * A wrapper around IDataService that forwards calls to implementations of {@link DataService}. 697 */ 698 private class IDataServiceWrapper extends IDataService.Stub { 699 @Override createDataServiceProvider(int slotIndex)700 public void createDataServiceProvider(int slotIndex) { 701 mHandler.obtainMessage(DATA_SERVICE_CREATE_DATA_SERVICE_PROVIDER, slotIndex, 0) 702 .sendToTarget(); 703 } 704 705 @Override removeDataServiceProvider(int slotIndex)706 public void removeDataServiceProvider(int slotIndex) { 707 mHandler.obtainMessage(DATA_SERVICE_REMOVE_DATA_SERVICE_PROVIDER, slotIndex, 0) 708 .sendToTarget(); 709 } 710 711 @Override setupDataCall(int slotIndex, int accessNetworkType, DataProfile dataProfile, boolean isRoaming, boolean allowRoaming, int reason, LinkProperties linkProperties, int pduSessionId, NetworkSliceInfo sliceInfo, TrafficDescriptor trafficDescriptor, boolean matchAllRuleAllowed, IDataServiceCallback callback)712 public void setupDataCall(int slotIndex, int accessNetworkType, DataProfile dataProfile, 713 boolean isRoaming, boolean allowRoaming, int reason, 714 LinkProperties linkProperties, int pduSessionId, NetworkSliceInfo sliceInfo, 715 TrafficDescriptor trafficDescriptor, boolean matchAllRuleAllowed, 716 IDataServiceCallback callback) { 717 mHandler.obtainMessage(DATA_SERVICE_REQUEST_SETUP_DATA_CALL, slotIndex, 0, 718 new SetupDataCallRequest(accessNetworkType, dataProfile, isRoaming, 719 allowRoaming, reason, linkProperties, pduSessionId, sliceInfo, 720 trafficDescriptor, matchAllRuleAllowed, callback)) 721 .sendToTarget(); 722 } 723 724 @Override deactivateDataCall(int slotIndex, int cid, int reason, IDataServiceCallback callback)725 public void deactivateDataCall(int slotIndex, int cid, int reason, 726 IDataServiceCallback callback) { 727 mHandler.obtainMessage(DATA_SERVICE_REQUEST_DEACTIVATE_DATA_CALL, slotIndex, 0, 728 new DeactivateDataCallRequest(cid, reason, callback)) 729 .sendToTarget(); 730 } 731 732 @Override setInitialAttachApn(int slotIndex, DataProfile dataProfile, boolean isRoaming, IDataServiceCallback callback)733 public void setInitialAttachApn(int slotIndex, DataProfile dataProfile, boolean isRoaming, 734 IDataServiceCallback callback) { 735 mHandler.obtainMessage(DATA_SERVICE_REQUEST_SET_INITIAL_ATTACH_APN, slotIndex, 0, 736 new SetInitialAttachApnRequest(dataProfile, isRoaming, callback)) 737 .sendToTarget(); 738 } 739 740 @Override setDataProfile(int slotIndex, List<DataProfile> dps, boolean isRoaming, IDataServiceCallback callback)741 public void setDataProfile(int slotIndex, List<DataProfile> dps, boolean isRoaming, 742 IDataServiceCallback callback) { 743 mHandler.obtainMessage(DATA_SERVICE_REQUEST_SET_DATA_PROFILE, slotIndex, 0, 744 new SetDataProfileRequest(dps, isRoaming, callback)).sendToTarget(); 745 } 746 747 @Override requestDataCallList(int slotIndex, IDataServiceCallback callback)748 public void requestDataCallList(int slotIndex, IDataServiceCallback callback) { 749 if (callback == null) { 750 loge("requestDataCallList: callback is null"); 751 return; 752 } 753 mHandler.obtainMessage(DATA_SERVICE_REQUEST_REQUEST_DATA_CALL_LIST, slotIndex, 0, 754 callback).sendToTarget(); 755 } 756 757 @Override registerForDataCallListChanged(int slotIndex, IDataServiceCallback callback)758 public void registerForDataCallListChanged(int slotIndex, IDataServiceCallback callback) { 759 if (callback == null) { 760 loge("registerForDataCallListChanged: callback is null"); 761 return; 762 } 763 mHandler.obtainMessage(DATA_SERVICE_REQUEST_REGISTER_DATA_CALL_LIST_CHANGED, slotIndex, 764 0, callback).sendToTarget(); 765 } 766 767 @Override unregisterForDataCallListChanged(int slotIndex, IDataServiceCallback callback)768 public void unregisterForDataCallListChanged(int slotIndex, IDataServiceCallback callback) { 769 if (callback == null) { 770 loge("unregisterForDataCallListChanged: callback is null"); 771 return; 772 } 773 mHandler.obtainMessage(DATA_SERVICE_REQUEST_UNREGISTER_DATA_CALL_LIST_CHANGED, 774 slotIndex, 0, callback).sendToTarget(); 775 } 776 777 @Override startHandover(int slotIndex, int cid, IDataServiceCallback callback)778 public void startHandover(int slotIndex, int cid, IDataServiceCallback callback) { 779 if (callback == null) { 780 loge("startHandover: callback is null"); 781 return; 782 } 783 BeginCancelHandoverRequest req = new BeginCancelHandoverRequest(cid, callback); 784 mHandler.obtainMessage(DATA_SERVICE_REQUEST_START_HANDOVER, 785 slotIndex, 0, req) 786 .sendToTarget(); 787 } 788 789 @Override cancelHandover(int slotIndex, int cid, IDataServiceCallback callback)790 public void cancelHandover(int slotIndex, int cid, IDataServiceCallback callback) { 791 if (callback == null) { 792 loge("cancelHandover: callback is null"); 793 return; 794 } 795 BeginCancelHandoverRequest req = new BeginCancelHandoverRequest(cid, callback); 796 mHandler.obtainMessage(DATA_SERVICE_REQUEST_CANCEL_HANDOVER, 797 slotIndex, 0, req).sendToTarget(); 798 } 799 800 @Override registerForUnthrottleApn(int slotIndex, IDataServiceCallback callback)801 public void registerForUnthrottleApn(int slotIndex, IDataServiceCallback callback) { 802 if (callback == null) { 803 loge("registerForUnthrottleApn: callback is null"); 804 return; 805 } 806 mHandler.obtainMessage(DATA_SERVICE_REQUEST_REGISTER_APN_UNTHROTTLED, slotIndex, 807 0, callback).sendToTarget(); 808 } 809 810 @Override unregisterForUnthrottleApn(int slotIndex, IDataServiceCallback callback)811 public void unregisterForUnthrottleApn(int slotIndex, IDataServiceCallback callback) { 812 if (callback == null) { 813 loge("uregisterForUnthrottleApn: callback is null"); 814 return; 815 } 816 mHandler.obtainMessage(DATA_SERVICE_REQUEST_UNREGISTER_APN_UNTHROTTLED, 817 slotIndex, 0, callback).sendToTarget(); 818 } 819 } 820 log(String s)821 private void log(String s) { 822 Rlog.d(TAG, s); 823 } 824 loge(String s)825 private void loge(String s) { 826 Rlog.e(TAG, s); 827 } 828 } 829