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