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