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