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