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