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