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