• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2018 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 com.android.internal.telephony.dataconnection;
18 
19 import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
20 import static android.text.format.DateUtils.SECOND_IN_MILLIS;
21 
22 import android.annotation.NonNull;
23 import android.annotation.Nullable;
24 import android.app.AppOpsManager;
25 import android.content.BroadcastReceiver;
26 import android.content.ComponentName;
27 import android.content.Context;
28 import android.content.Intent;
29 import android.content.IntentFilter;
30 import android.content.ServiceConnection;
31 import android.content.pm.PackageManager;
32 import android.content.pm.ResolveInfo;
33 import android.net.LinkProperties;
34 import android.os.AsyncResult;
35 import android.os.Handler;
36 import android.os.IBinder;
37 import android.os.Message;
38 import android.os.PersistableBundle;
39 import android.os.RegistrantList;
40 import android.os.RemoteException;
41 import android.os.UserHandle;
42 import android.permission.LegacyPermissionManager;
43 import android.telephony.AccessNetworkConstants;
44 import android.telephony.AccessNetworkConstants.TransportType;
45 import android.telephony.AnomalyReporter;
46 import android.telephony.CarrierConfigManager;
47 import android.telephony.SubscriptionManager;
48 import android.telephony.data.DataCallResponse;
49 import android.telephony.data.DataProfile;
50 import android.telephony.data.DataService;
51 import android.telephony.data.DataServiceCallback;
52 import android.telephony.data.IDataService;
53 import android.telephony.data.IDataServiceCallback;
54 import android.telephony.data.NetworkSliceInfo;
55 import android.telephony.data.TrafficDescriptor;
56 import android.text.TextUtils;
57 
58 import com.android.internal.telephony.Phone;
59 import com.android.internal.telephony.PhoneConfigurationManager;
60 import com.android.internal.telephony.util.TelephonyUtils;
61 import com.android.telephony.Rlog;
62 
63 import java.util.HashSet;
64 import java.util.List;
65 import java.util.Map;
66 import java.util.Set;
67 import java.util.UUID;
68 import java.util.concurrent.ConcurrentHashMap;
69 import java.util.concurrent.CountDownLatch;
70 
71 /**
72  * Data service manager manages handling data requests and responses on data services (e.g.
73  * Cellular data service, IWLAN data service).
74  */
75 public class DataServiceManager extends Handler {
76     private static final boolean DBG = true;
77 
78     static final String DATA_CALL_RESPONSE = "data_call_response";
79 
80     private static final int EVENT_BIND_DATA_SERVICE = 1;
81 
82     private static final int EVENT_WATCHDOG_TIMEOUT = 2;
83 
84     private static final long REQUEST_UNRESPONDED_TIMEOUT = 10 * MINUTE_IN_MILLIS; // 10 mins
85 
86     private static final long CHANGE_PERMISSION_TIMEOUT_MS = 15 * SECOND_IN_MILLIS; // 15 secs
87 
88     private final Phone mPhone;
89 
90     private final String mTag;
91 
92     private final CarrierConfigManager mCarrierConfigManager;
93     private final AppOpsManager mAppOps;
94     private final LegacyPermissionManager mPermissionManager;
95 
96     private final int mTransportType;
97 
98     private boolean mBound;
99 
100     private IDataService mIDataService;
101 
102     private DataServiceManagerDeathRecipient mDeathRecipient;
103 
104     private final RegistrantList mServiceBindingChangedRegistrants = new RegistrantList();
105 
106     private final Map<IBinder, Message> mMessageMap = new ConcurrentHashMap<>();
107 
108     private final RegistrantList mDataCallListChangedRegistrants = new RegistrantList();
109 
110     private final RegistrantList mApnUnthrottledRegistrants = new RegistrantList();
111 
112     private String mTargetBindingPackageName;
113 
114     private CellularDataServiceConnection mServiceConnection;
115 
116     private final UUID mAnomalyUUID = UUID.fromString("fc1956de-c080-45de-8431-a1faab687110");
117     private String mLastBoundPackageName;
118 
119     /**
120      * Helpful for logging
121      * @return the tag name
122      *
123      * @hide
124      */
getTag()125     public String getTag() {
126         return mTag;
127     }
128 
129     private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
130         @Override
131         public void onReceive(Context context, Intent intent) {
132             final String action = intent.getAction();
133             if (CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED.equals(action)
134                     && mPhone.getPhoneId() == intent.getIntExtra(
135                     CarrierConfigManager.EXTRA_SLOT_INDEX, 0)) {
136                 // We should wait for carrier config changed event because the target binding
137                 // package name can come from the carrier config. Note that we still get this event
138                 // even when SIM is absent.
139                 if (DBG) log("Carrier config changed. Try to bind data service.");
140                 sendEmptyMessage(EVENT_BIND_DATA_SERVICE);
141             }
142         }
143     };
144 
145     private class DataServiceManagerDeathRecipient implements IBinder.DeathRecipient {
146         @Override
binderDied()147         public void binderDied() {
148             // TODO: try to rebind the service.
149             String message = "Data service " + mLastBoundPackageName +  " for transport type "
150                     + AccessNetworkConstants.transportTypeToString(mTransportType) + " died.";
151             loge(message);
152             AnomalyReporter.reportAnomaly(mAnomalyUUID, message);
153         }
154     }
155 
grantPermissionsToService(String packageName)156     private void grantPermissionsToService(String packageName) {
157         final String[] pkgToGrant = {packageName};
158         CountDownLatch latch = new CountDownLatch(1);
159         try {
160             mPermissionManager.grantDefaultPermissionsToEnabledTelephonyDataServices(
161                     pkgToGrant, UserHandle.of(UserHandle.myUserId()), Runnable::run,
162                     isSuccess -> {
163                         if (isSuccess) {
164                             latch.countDown();
165                         } else {
166                             loge("Failed to grant permissions to service.");
167                         }
168                     });
169             TelephonyUtils.waitUntilReady(latch, CHANGE_PERMISSION_TIMEOUT_MS);
170             mAppOps.setMode(AppOpsManager.OPSTR_MANAGE_IPSEC_TUNNELS,
171                     UserHandle.myUserId(), pkgToGrant[0], AppOpsManager.MODE_ALLOWED);
172             mAppOps.setMode(AppOpsManager.OPSTR_FINE_LOCATION,
173                     UserHandle.myUserId(), pkgToGrant[0], AppOpsManager.MODE_ALLOWED);
174         } catch (RuntimeException e) {
175             loge("Binder to package manager died, permission grant for DataService failed.");
176             throw e;
177         }
178     }
179 
180     /**
181      * Loop through all DataServices installed on the system and revoke permissions from any that
182      * are not currently the WWAN or WLAN data service.
183      */
revokePermissionsFromUnusedDataServices()184     private void revokePermissionsFromUnusedDataServices() {
185         // Except the current data services from having their permissions removed.
186         Set<String> dataServices = getAllDataServicePackageNames();
187         for (int transportType : mPhone.getTransportManager().getAvailableTransports()) {
188             dataServices.remove(getDataServicePackageName(transportType));
189         }
190 
191         CountDownLatch latch = new CountDownLatch(1);
192         try {
193             String[] dataServicesArray = new String[dataServices.size()];
194             dataServices.toArray(dataServicesArray);
195             mPermissionManager.revokeDefaultPermissionsFromDisabledTelephonyDataServices(
196                     dataServicesArray, UserHandle.of(UserHandle.myUserId()), Runnable::run,
197                     isSuccess -> {
198                         if (isSuccess) {
199                             latch.countDown();
200                         } else {
201                             loge("Failed to revoke permissions from data services.");
202                         }
203                     });
204             TelephonyUtils.waitUntilReady(latch, CHANGE_PERMISSION_TIMEOUT_MS);
205             for (String pkg : dataServices) {
206                 mAppOps.setMode(AppOpsManager.OPSTR_MANAGE_IPSEC_TUNNELS, UserHandle.myUserId(),
207                         pkg, AppOpsManager.MODE_ERRORED);
208                 mAppOps.setMode(AppOpsManager.OPSTR_FINE_LOCATION, UserHandle.myUserId(),
209                         pkg, AppOpsManager.MODE_ERRORED);
210             }
211         } catch (RuntimeException e) {
212             loge("Binder to package manager died; failed to revoke DataService permissions.");
213             throw e;
214         }
215     }
216 
217     private final class CellularDataServiceConnection implements ServiceConnection {
218         @Override
onServiceConnected(ComponentName name, IBinder service)219         public void onServiceConnected(ComponentName name, IBinder service) {
220             if (DBG) log("onServiceConnected");
221             mIDataService = IDataService.Stub.asInterface(service);
222             mDeathRecipient = new DataServiceManagerDeathRecipient();
223             mBound = true;
224             mLastBoundPackageName = getDataServicePackageName();
225             removeMessages(EVENT_WATCHDOG_TIMEOUT);
226 
227             try {
228                 service.linkToDeath(mDeathRecipient, 0);
229                 mIDataService.createDataServiceProvider(mPhone.getPhoneId());
230                 mIDataService.registerForDataCallListChanged(mPhone.getPhoneId(),
231                         new CellularDataServiceCallback("dataCallListChanged"));
232                 mIDataService.registerForUnthrottleApn(mPhone.getPhoneId(),
233                         new CellularDataServiceCallback("unthrottleApn"));
234             } catch (RemoteException e) {
235                 loge("Remote exception. " + e);
236                 return;
237             }
238             mServiceBindingChangedRegistrants.notifyResult(true);
239         }
240         @Override
onServiceDisconnected(ComponentName name)241         public void onServiceDisconnected(ComponentName name) {
242             if (DBG) log("onServiceDisconnected");
243             removeMessages(EVENT_WATCHDOG_TIMEOUT);
244             mIDataService = null;
245             mBound = false;
246             mServiceBindingChangedRegistrants.notifyResult(false);
247             mTargetBindingPackageName = null;
248         }
249     }
250 
251     private final class CellularDataServiceCallback extends IDataServiceCallback.Stub {
252 
253         private final String mTag;
254 
CellularDataServiceCallback(String tag)255         CellularDataServiceCallback(String tag) {
256             mTag = tag;
257         }
258 
getTag()259         public String getTag() {
260             return mTag;
261         }
262 
263         @Override
onSetupDataCallComplete(@ataServiceCallback.ResultCode int resultCode, DataCallResponse response)264         public void onSetupDataCallComplete(@DataServiceCallback.ResultCode int resultCode,
265                                             DataCallResponse response) {
266             if (DBG) {
267                 log("onSetupDataCallComplete. resultCode = " + resultCode + ", response = "
268                         + response);
269             }
270             removeMessages(EVENT_WATCHDOG_TIMEOUT, CellularDataServiceCallback.this);
271             Message msg = mMessageMap.remove(asBinder());
272             if (msg != null) {
273                 msg.getData().putParcelable(DATA_CALL_RESPONSE, response);
274                 sendCompleteMessage(msg, resultCode);
275             } else {
276                 loge("Unable to find the message for setup call response.");
277             }
278         }
279 
280         @Override
onDeactivateDataCallComplete(@ataServiceCallback.ResultCode int resultCode)281         public void onDeactivateDataCallComplete(@DataServiceCallback.ResultCode int resultCode) {
282             if (DBG) log("onDeactivateDataCallComplete. resultCode = " + resultCode);
283             removeMessages(EVENT_WATCHDOG_TIMEOUT, CellularDataServiceCallback.this);
284             Message msg = mMessageMap.remove(asBinder());
285             sendCompleteMessage(msg, resultCode);
286         }
287 
288         @Override
onSetInitialAttachApnComplete(@ataServiceCallback.ResultCode int resultCode)289         public void onSetInitialAttachApnComplete(@DataServiceCallback.ResultCode int resultCode) {
290             if (DBG) log("onSetInitialAttachApnComplete. resultCode = " + resultCode);
291             Message msg = mMessageMap.remove(asBinder());
292             sendCompleteMessage(msg, resultCode);
293         }
294 
295         @Override
onSetDataProfileComplete(@ataServiceCallback.ResultCode int resultCode)296         public void onSetDataProfileComplete(@DataServiceCallback.ResultCode int resultCode) {
297             if (DBG) log("onSetDataProfileComplete. resultCode = " + resultCode);
298             Message msg = mMessageMap.remove(asBinder());
299             sendCompleteMessage(msg, resultCode);
300         }
301 
302         @Override
onRequestDataCallListComplete(@ataServiceCallback.ResultCode int resultCode, List<DataCallResponse> dataCallList)303         public void onRequestDataCallListComplete(@DataServiceCallback.ResultCode int resultCode,
304                                               List<DataCallResponse> dataCallList) {
305             if (DBG) log("onRequestDataCallListComplete. resultCode = " + resultCode);
306             Message msg = mMessageMap.remove(asBinder());
307             sendCompleteMessage(msg, resultCode);
308         }
309 
310         @Override
onDataCallListChanged(List<DataCallResponse> dataCallList)311         public void onDataCallListChanged(List<DataCallResponse> dataCallList) {
312             mDataCallListChangedRegistrants.notifyRegistrants(
313                     new AsyncResult(null, dataCallList, null));
314         }
315 
316         @Override
onHandoverStarted(@ataServiceCallback.ResultCode int resultCode)317         public void onHandoverStarted(@DataServiceCallback.ResultCode int resultCode) {
318             if (DBG) log("onHandoverStarted. resultCode = " + resultCode);
319             removeMessages(EVENT_WATCHDOG_TIMEOUT, CellularDataServiceCallback.this);
320             Message msg = mMessageMap.remove(asBinder());
321             sendCompleteMessage(msg, resultCode);
322         }
323 
324         @Override
onHandoverCancelled(@ataServiceCallback.ResultCode int resultCode)325         public void onHandoverCancelled(@DataServiceCallback.ResultCode int resultCode) {
326             if (DBG) log("onHandoverCancelled. resultCode = " + resultCode);
327             removeMessages(EVENT_WATCHDOG_TIMEOUT, CellularDataServiceCallback.this);
328             Message msg = mMessageMap.remove(asBinder());
329             sendCompleteMessage(msg, resultCode);
330         }
331 
onApnUnthrottled(String apn)332         public void onApnUnthrottled(String apn) {
333             if (apn != null) {
334                 mApnUnthrottledRegistrants.notifyRegistrants(
335                         new AsyncResult(null, apn, null));
336             } else {
337                 loge("onApnUnthrottled: apn is null");
338             }
339         }
340     }
341 
342     /**
343      * Constructor
344      *
345      * @param phone The phone object
346      * @param transportType The transport type
347      * @param tagSuffix Logging tag suffix
348      */
DataServiceManager(Phone phone, @TransportType int transportType, String tagSuffix)349     public DataServiceManager(Phone phone, @TransportType int transportType, String tagSuffix) {
350         mPhone = phone;
351         mTag = "DSM" + tagSuffix;
352         mTransportType = transportType;
353         mBound = false;
354         mCarrierConfigManager = (CarrierConfigManager) phone.getContext().getSystemService(
355                 Context.CARRIER_CONFIG_SERVICE);
356         // NOTE: Do NOT use AppGlobals to retrieve the permission manager; AppGlobals
357         // caches the service instance, but we need to explicitly request a new service
358         // so it can be mocked out for tests
359         mPermissionManager = (LegacyPermissionManager) phone.getContext().getSystemService(
360                 Context.LEGACY_PERMISSION_SERVICE);
361         mAppOps = (AppOpsManager) phone.getContext().getSystemService(Context.APP_OPS_SERVICE);
362 
363         IntentFilter intentFilter = new IntentFilter();
364         intentFilter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
365         try {
366             Context contextAsUser = phone.getContext().createPackageContextAsUser(
367                 phone.getContext().getPackageName(), 0, UserHandle.ALL);
368             contextAsUser.registerReceiver(mBroadcastReceiver, intentFilter,
369                 null /* broadcastPermission */, null);
370         } catch (PackageManager.NameNotFoundException e) {
371             loge("Package name not found: " + e.getMessage());
372         }
373         PhoneConfigurationManager.registerForMultiSimConfigChange(
374                 this, EVENT_BIND_DATA_SERVICE, null);
375 
376         sendEmptyMessage(EVENT_BIND_DATA_SERVICE);
377     }
378 
379     /**
380      * Handle message events
381      *
382      * @param msg The message to handle
383      */
384     @Override
handleMessage(Message msg)385     public void handleMessage(Message msg) {
386         switch (msg.what) {
387             case EVENT_BIND_DATA_SERVICE:
388                 rebindDataService();
389                 break;
390             case EVENT_WATCHDOG_TIMEOUT:
391                 handleRequestUnresponded((CellularDataServiceCallback) msg.obj);
392                 break;
393             default:
394                 loge("Unhandled event " + msg.what);
395         }
396     }
397 
handleRequestUnresponded(CellularDataServiceCallback callback)398     private void handleRequestUnresponded(CellularDataServiceCallback callback) {
399         String message = "Request " + callback.getTag() + " unresponded on transport "
400                 + AccessNetworkConstants.transportTypeToString(mTransportType) + " in "
401                 + REQUEST_UNRESPONDED_TIMEOUT / 1000 + " seconds.";
402         log(message);
403         // Using fixed UUID to avoid duplicate bugreport notification
404         AnomalyReporter.reportAnomaly(
405                 UUID.fromString("f5d5cbe6-9bd6-4009-b764-42b1b649b1de"),
406                 message);
407     }
408 
unbindDataService()409     private void unbindDataService() {
410         // Start by cleaning up all packages that *shouldn't* have permissions.
411         revokePermissionsFromUnusedDataServices();
412         if (mIDataService != null && mIDataService.asBinder().isBinderAlive()) {
413             log("unbinding service");
414             // Remove the network availability updater and then unbind the service.
415             try {
416                 mIDataService.removeDataServiceProvider(mPhone.getPhoneId());
417             } catch (RemoteException e) {
418                 loge("Cannot remove data service provider. " + e);
419             }
420         }
421 
422         if (mServiceConnection != null) {
423             mPhone.getContext().unbindService(mServiceConnection);
424         }
425         mIDataService = null;
426         mServiceConnection = null;
427         mTargetBindingPackageName = null;
428         mBound = false;
429     }
430 
bindDataService(String packageName)431     private void bindDataService(String packageName) {
432         if (mPhone == null || !SubscriptionManager.isValidPhoneId(mPhone.getPhoneId())) {
433             loge("can't bindDataService with invalid phone or phoneId.");
434             return;
435         }
436 
437         if (TextUtils.isEmpty(packageName)) {
438             loge("Can't find the binding package");
439             return;
440         }
441 
442         Intent intent = null;
443         String className = getDataServiceClassName();
444         if (TextUtils.isEmpty(className)) {
445             intent = new Intent(DataService.SERVICE_INTERFACE);
446             intent.setPackage(packageName);
447         } else {
448             ComponentName cm = new ComponentName(packageName, className);
449             intent = new Intent(DataService.SERVICE_INTERFACE).setComponent(cm);
450         }
451 
452         // Then pre-emptively grant the permissions to the package we will bind.
453         grantPermissionsToService(packageName);
454 
455         try {
456             mServiceConnection = new CellularDataServiceConnection();
457             if (!mPhone.getContext().bindService(
458                     intent, mServiceConnection, Context.BIND_AUTO_CREATE)) {
459                 loge("Cannot bind to the data service.");
460                 return;
461             }
462             mTargetBindingPackageName = packageName;
463         } catch (Exception e) {
464             loge("Cannot bind to the data service. Exception: " + e);
465         }
466     }
467 
rebindDataService()468     private void rebindDataService() {
469         String packageName = getDataServicePackageName();
470         // Do nothing if no need to rebind.
471         if (SubscriptionManager.isValidPhoneId(mPhone.getPhoneId())
472                 && TextUtils.equals(packageName, mTargetBindingPackageName)) {
473             if (DBG) log("Service " + packageName + " already bound or being bound.");
474             return;
475         }
476 
477         unbindDataService();
478         bindDataService(packageName);
479     }
480 
481     @NonNull
getAllDataServicePackageNames()482     private Set<String> getAllDataServicePackageNames() {
483         // Cowardly using the public PackageManager interface here.
484         // Note: This matches only packages that were installed on the system image. If we ever
485         // expand the permissions model to allow CarrierPrivileged packages, then this will need
486         // to be updated.
487         List<ResolveInfo> dataPackages =
488                 mPhone.getContext().getPackageManager().queryIntentServices(
489                         new Intent(DataService.SERVICE_INTERFACE),
490                                 PackageManager.MATCH_SYSTEM_ONLY);
491         HashSet<String> packageNames = new HashSet<>();
492         for (ResolveInfo info : dataPackages) {
493             if (info.serviceInfo == null) continue;
494             packageNames.add(info.serviceInfo.packageName);
495         }
496         return packageNames;
497     }
498 
499     /**
500      * Get the data service package name for our current transport type.
501      *
502      * @return package name of the data service package for the the current transportType.
503      */
getDataServicePackageName()504     public String getDataServicePackageName() {
505         return getDataServicePackageName(mTransportType);
506     }
507 
508     /**
509      * Get the data service package by transport type.
510      *
511      * When we bind to a DataService package, we need to revoke permissions from stale
512      * packages; we need to exclude data packages for all transport types, so we need to
513      * to be able to query by transport type.
514      *
515      * @param transportType The transport type
516      * @return package name of the data service package for the specified transportType.
517      */
getDataServicePackageName(@ransportType int transportType)518     private String getDataServicePackageName(@TransportType int transportType) {
519         String packageName;
520         int resourceId;
521         String carrierConfig;
522 
523         switch (transportType) {
524             case AccessNetworkConstants.TRANSPORT_TYPE_WWAN:
525                 resourceId = com.android.internal.R.string.config_wwan_data_service_package;
526                 carrierConfig = CarrierConfigManager
527                         .KEY_CARRIER_DATA_SERVICE_WWAN_PACKAGE_OVERRIDE_STRING;
528                 break;
529             case AccessNetworkConstants.TRANSPORT_TYPE_WLAN:
530                 resourceId = com.android.internal.R.string.config_wlan_data_service_package;
531                 carrierConfig = CarrierConfigManager
532                         .KEY_CARRIER_DATA_SERVICE_WLAN_PACKAGE_OVERRIDE_STRING;
533                 break;
534             default:
535                 throw new IllegalStateException("Transport type not WWAN or WLAN. type="
536                         + AccessNetworkConstants.transportTypeToString(mTransportType));
537         }
538 
539         // Read package name from resource overlay
540         packageName = mPhone.getContext().getResources().getString(resourceId);
541 
542         PersistableBundle b = mCarrierConfigManager.getConfigForSubId(mPhone.getSubId());
543 
544         if (b != null && !TextUtils.isEmpty(b.getString(carrierConfig))) {
545             // If carrier config overrides it, use the one from carrier config
546             packageName = b.getString(carrierConfig, packageName);
547         }
548 
549         return packageName;
550     }
551 
552     /**
553      * Get the data service class name for our current transport type.
554      *
555      * @return class name of the data service package for the the current transportType.
556      */
getDataServiceClassName()557     private String getDataServiceClassName() {
558         return getDataServiceClassName(mTransportType);
559     }
560 
561 
562     /**
563      * Get the data service class by transport type.
564      *
565      * @param transportType either WWAN or WLAN
566      * @return class name of the data service package for the specified transportType.
567      */
getDataServiceClassName(int transportType)568     private String getDataServiceClassName(int transportType) {
569         String className;
570         int resourceId;
571         String carrierConfig;
572         switch (transportType) {
573             case AccessNetworkConstants.TRANSPORT_TYPE_WWAN:
574                 resourceId = com.android.internal.R.string.config_wwan_data_service_class;
575                 carrierConfig = CarrierConfigManager
576                         .KEY_CARRIER_DATA_SERVICE_WWAN_CLASS_OVERRIDE_STRING;
577                 break;
578             case AccessNetworkConstants.TRANSPORT_TYPE_WLAN:
579                 resourceId = com.android.internal.R.string.config_wlan_data_service_class;
580                 carrierConfig = CarrierConfigManager
581                         .KEY_CARRIER_DATA_SERVICE_WLAN_CLASS_OVERRIDE_STRING;
582                 break;
583             default:
584                 throw new IllegalStateException("Transport type not WWAN or WLAN. type="
585                         + transportType);
586         }
587 
588         // Read package name from resource overlay
589         className = mPhone.getContext().getResources().getString(resourceId);
590 
591         PersistableBundle b = mCarrierConfigManager.getConfigForSubId(mPhone.getSubId());
592 
593         if (b != null && !TextUtils.isEmpty(b.getString(carrierConfig))) {
594             // If carrier config overrides it, use the one from carrier config
595             className = b.getString(carrierConfig, className);
596         }
597 
598         return className;
599     }
600 
sendCompleteMessage(Message msg, @DataServiceCallback.ResultCode int code)601     private void sendCompleteMessage(Message msg, @DataServiceCallback.ResultCode int code) {
602         if (msg != null) {
603             msg.arg1 = code;
604             msg.sendToTarget();
605         }
606     }
607 
608     /**
609      * Setup a data connection. The data service provider must implement this method to support
610      * establishing a packet data connection. When completed or error, the service must invoke
611      * the provided callback to notify the platform.
612      *
613      * @param accessNetworkType Access network type that the data call will be established on.
614      *        Must be one of {@link AccessNetworkConstants.AccessNetworkType}.
615      * @param dataProfile Data profile used for data call setup. See {@link DataProfile}
616      * @param isRoaming True if the device is data roaming.
617      * @param allowRoaming True if data roaming is allowed by the user.
618      * @param reason The reason for data setup. Must be {@link DataService#REQUEST_REASON_NORMAL} or
619      *        {@link DataService#REQUEST_REASON_HANDOVER}.
620      * @param linkProperties If {@code reason} is {@link DataService#REQUEST_REASON_HANDOVER}, this
621      *        is the link properties of the existing data connection, otherwise null.
622      * @param pduSessionId The pdu session id to be used for this data call.  A value of -1 means
623      *                     no pdu session id was attached to this call.
624      *                     Reference: 3GPP TS 24.007 Section 11.2.3.1b
625      * @param sliceInfo The slice that represents S-NSSAI.
626      *                  Reference: 3GPP TS 24.501
627      * @param trafficDescriptor The traffic descriptor for this data call, used for URSP matching.
628      *                          Reference: 3GPP TS TS 24.526 Section 5.2
629      * @param matchAllRuleAllowed True if using the default match-all URSP rule for this request is
630      *                            allowed.
631      * @param onCompleteMessage The result message for this request. Null if the client does not
632      *        care about the result.
633      */
setupDataCall(int accessNetworkType, DataProfile dataProfile, boolean isRoaming, boolean allowRoaming, int reason, LinkProperties linkProperties, int pduSessionId, @Nullable NetworkSliceInfo sliceInfo, @Nullable TrafficDescriptor trafficDescriptor, boolean matchAllRuleAllowed, Message onCompleteMessage)634     public void setupDataCall(int accessNetworkType, DataProfile dataProfile, boolean isRoaming,
635             boolean allowRoaming, int reason, LinkProperties linkProperties, int pduSessionId,
636             @Nullable NetworkSliceInfo sliceInfo, @Nullable TrafficDescriptor trafficDescriptor,
637             boolean matchAllRuleAllowed, Message onCompleteMessage) {
638         if (DBG) log("setupDataCall");
639         if (!mBound) {
640             loge("setupDataCall: Data service not bound.");
641             sendCompleteMessage(onCompleteMessage, DataServiceCallback.RESULT_ERROR_ILLEGAL_STATE);
642             return;
643         }
644 
645         CellularDataServiceCallback callback = new CellularDataServiceCallback("setupDataCall");
646         if (onCompleteMessage != null) {
647             mMessageMap.put(callback.asBinder(), onCompleteMessage);
648         }
649         try {
650             sendMessageDelayed(obtainMessage(EVENT_WATCHDOG_TIMEOUT, callback),
651                     REQUEST_UNRESPONDED_TIMEOUT);
652             mIDataService.setupDataCall(mPhone.getPhoneId(), accessNetworkType, dataProfile,
653                     isRoaming, allowRoaming, reason, linkProperties, pduSessionId, sliceInfo,
654                     trafficDescriptor, matchAllRuleAllowed, callback);
655         } catch (RemoteException e) {
656             loge("setupDataCall: Cannot invoke setupDataCall on data service.");
657             mMessageMap.remove(callback.asBinder());
658             sendCompleteMessage(onCompleteMessage, DataServiceCallback.RESULT_ERROR_ILLEGAL_STATE);
659         }
660     }
661 
662     /**
663      * Deactivate a data connection. The data service provider must implement this method to
664      * support data connection tear down. When completed or error, the service must invoke the
665      * provided callback to notify the platform.
666      *
667      * @param cid Call id returned in the callback of {@link #setupDataCall(int, DataProfile,
668      *        boolean, boolean, int, LinkProperties, Message)}
669      * @param reason The reason for data deactivation. Must be
670      *        {@link DataService#REQUEST_REASON_NORMAL}, {@link DataService#REQUEST_REASON_SHUTDOWN}
671      *        or {@link DataService#REQUEST_REASON_HANDOVER}.
672      * @param onCompleteMessage The result message for this request. Null if the client does not
673      *        care about the result.
674      */
deactivateDataCall(int cid, int reason, Message onCompleteMessage)675     public void deactivateDataCall(int cid, int reason, Message onCompleteMessage) {
676         if (DBG) log("deactivateDataCall");
677         if (!mBound) {
678             loge("Data service not bound.");
679             sendCompleteMessage(onCompleteMessage, DataServiceCallback.RESULT_ERROR_ILLEGAL_STATE);
680             return;
681         }
682 
683         CellularDataServiceCallback callback =
684                 new CellularDataServiceCallback("deactivateDataCall");
685         if (onCompleteMessage != null) {
686             mMessageMap.put(callback.asBinder(), onCompleteMessage);
687         }
688         try {
689             sendMessageDelayed(obtainMessage(EVENT_WATCHDOG_TIMEOUT, callback),
690                     REQUEST_UNRESPONDED_TIMEOUT);
691             mIDataService.deactivateDataCall(mPhone.getPhoneId(), cid, reason, callback);
692         } catch (RemoteException e) {
693             loge("Cannot invoke deactivateDataCall on data service.");
694             mMessageMap.remove(callback.asBinder());
695             sendCompleteMessage(onCompleteMessage, DataServiceCallback.RESULT_ERROR_ILLEGAL_STATE);
696         }
697     }
698 
699     /**
700      * Indicates that a handover has begun.  This is called on the source transport.
701      *
702      * Any resources being transferred cannot be released while a
703      * handover is underway.
704      *
705      * If a handover was unsuccessful, then the framework calls DataServiceManager#cancelHandover.
706      * The target transport retains ownership over any of the resources being transferred.
707      *
708      * If a handover was successful, the framework calls DataServiceManager#deactivateDataCall with
709      * reason HANDOVER. The target transport now owns the transferred resources and is
710      * responsible for releasing them.
711      *
712      * @param cid The identifier of the data call which is provided in DataCallResponse
713      * @param onCompleteMessage The result callback for this request.
714      */
startHandover(int cid, @NonNull Message onCompleteMessage)715     public void startHandover(int cid, @NonNull Message onCompleteMessage) {
716         CellularDataServiceCallback callback =
717                 setupCallbackHelper("startHandover", onCompleteMessage);
718         if (callback == null) {
719             loge("startHandover: callback == null");
720             sendCompleteMessage(onCompleteMessage, DataServiceCallback.RESULT_ERROR_ILLEGAL_STATE);
721             return;
722         }
723 
724         try {
725             sendMessageDelayed(obtainMessage(EVENT_WATCHDOG_TIMEOUT, callback),
726                     REQUEST_UNRESPONDED_TIMEOUT);
727             mIDataService.startHandover(mPhone.getPhoneId(), cid, callback);
728         } catch (RemoteException e) {
729             loge("Cannot invoke startHandover on data service.");
730             mMessageMap.remove(callback.asBinder());
731             sendCompleteMessage(onCompleteMessage, DataServiceCallback.RESULT_ERROR_ILLEGAL_STATE);
732         }
733     }
734 
735     /**
736      * Indicates that a handover was cancelled after a call to DataServiceManager#startHandover.
737      * This is called on the source transport.
738      *
739      * Since the handover was unsuccessful, the source transport retains ownership over any of
740      * the resources being transferred and is still responsible for releasing them.
741      *
742      * @param cid The identifier of the data call which is provided in DataCallResponse
743      * @param onCompleteMessage The result callback for this request.
744      */
cancelHandover(int cid, @NonNull Message onCompleteMessage)745     public void cancelHandover(int cid, @NonNull Message onCompleteMessage) {
746         CellularDataServiceCallback callback =
747                 setupCallbackHelper("cancelHandover", onCompleteMessage);
748         if (callback == null) {
749             sendCompleteMessage(onCompleteMessage, DataServiceCallback.RESULT_ERROR_ILLEGAL_STATE);
750             return;
751         }
752 
753         try {
754             sendMessageDelayed(obtainMessage(EVENT_WATCHDOG_TIMEOUT, callback),
755                     REQUEST_UNRESPONDED_TIMEOUT);
756             mIDataService.cancelHandover(mPhone.getPhoneId(), cid, callback);
757         } catch (RemoteException e) {
758             loge("Cannot invoke cancelHandover on data service.");
759             mMessageMap.remove(callback.asBinder());
760             sendCompleteMessage(onCompleteMessage, DataServiceCallback.RESULT_ERROR_ILLEGAL_STATE);
761         }
762     }
763 
764     @Nullable
setupCallbackHelper( @onNull final String operationName, @NonNull final Message onCompleteMessage)765     private CellularDataServiceCallback setupCallbackHelper(
766             @NonNull final String operationName, @NonNull final Message onCompleteMessage) {
767         if (DBG) log(operationName);
768         if (!mBound) {
769             sendCompleteMessage(onCompleteMessage, DataServiceCallback.RESULT_ERROR_ILLEGAL_STATE);
770             return null;
771         }
772 
773         CellularDataServiceCallback callback =
774                 new CellularDataServiceCallback(operationName);
775         if (onCompleteMessage != null) {
776             if (DBG) log(operationName + ": onCompleteMessage set");
777             mMessageMap.put(callback.asBinder(), onCompleteMessage);
778         } else {
779             if (DBG) log(operationName + ": onCompleteMessage not set");
780         }
781         return callback;
782     }
783 
784     /**
785      * Set an APN to initial attach network.
786      *
787      * @param dataProfile Data profile used for data call setup. See {@link DataProfile}.
788      * @param isRoaming True if the device is data roaming.
789      * @param onCompleteMessage The result message for this request. Null if the client does not
790      *        care about the result.
791      */
setInitialAttachApn(DataProfile dataProfile, boolean isRoaming, Message onCompleteMessage)792     public void setInitialAttachApn(DataProfile dataProfile, boolean isRoaming,
793                                     Message onCompleteMessage) {
794         if (DBG) log("setInitialAttachApn");
795         if (!mBound) {
796             loge("Data service not bound.");
797             sendCompleteMessage(onCompleteMessage, DataServiceCallback.RESULT_ERROR_ILLEGAL_STATE);
798             return;
799         }
800 
801         CellularDataServiceCallback callback =
802                 new CellularDataServiceCallback("setInitialAttachApn");
803         if (onCompleteMessage != null) {
804             mMessageMap.put(callback.asBinder(), onCompleteMessage);
805         }
806         try {
807             mIDataService.setInitialAttachApn(mPhone.getPhoneId(), dataProfile, isRoaming,
808                     callback);
809         } catch (RemoteException e) {
810             loge("Cannot invoke setInitialAttachApn on data service.");
811             mMessageMap.remove(callback.asBinder());
812             sendCompleteMessage(onCompleteMessage, DataServiceCallback.RESULT_ERROR_ILLEGAL_STATE);
813         }
814     }
815 
816     /**
817      * Send current carrier's data profiles to the data service for data call setup. This is
818      * only for CDMA carrier that can change the profile through OTA. The data service should
819      * always uses the latest data profile sent by the framework.
820      *
821      * @param dps A list of data profiles.
822      * @param isRoaming True if the device is data roaming.
823      * @param onCompleteMessage The result message for this request. Null if the client does not
824      *        care about the result.
825      */
setDataProfile(List<DataProfile> dps, boolean isRoaming, Message onCompleteMessage)826     public void setDataProfile(List<DataProfile> dps, boolean isRoaming,
827                                Message onCompleteMessage) {
828         if (DBG) log("setDataProfile");
829         if (!mBound) {
830             loge("Data service not bound.");
831             sendCompleteMessage(onCompleteMessage, DataServiceCallback.RESULT_ERROR_ILLEGAL_STATE);
832             return;
833         }
834 
835         CellularDataServiceCallback callback = new CellularDataServiceCallback("setDataProfile");
836         if (onCompleteMessage != null) {
837             mMessageMap.put(callback.asBinder(), onCompleteMessage);
838         }
839         try {
840             mIDataService.setDataProfile(mPhone.getPhoneId(), dps, isRoaming, callback);
841         } catch (RemoteException e) {
842             loge("Cannot invoke setDataProfile on data service.");
843             mMessageMap.remove(callback.asBinder());
844             sendCompleteMessage(onCompleteMessage, DataServiceCallback.RESULT_ERROR_ILLEGAL_STATE);
845         }
846     }
847 
848     /**
849      * Get the active data call list.
850      *
851      * @param onCompleteMessage The result message for this request. Null if the client does not
852      *        care about the result.
853      */
requestDataCallList(Message onCompleteMessage)854     public void requestDataCallList(Message onCompleteMessage) {
855         if (DBG) log("requestDataCallList");
856         if (!mBound) {
857             loge("Data service not bound.");
858             sendCompleteMessage(onCompleteMessage, DataServiceCallback.RESULT_ERROR_ILLEGAL_STATE);
859             return;
860         }
861 
862         CellularDataServiceCallback callback =
863                 new CellularDataServiceCallback("requestDataCallList");
864         if (onCompleteMessage != null) {
865             mMessageMap.put(callback.asBinder(), onCompleteMessage);
866         }
867         try {
868             mIDataService.requestDataCallList(mPhone.getPhoneId(), callback);
869         } catch (RemoteException e) {
870             loge("Cannot invoke requestDataCallList on data service.");
871             if (callback != null) {
872                 mMessageMap.remove(callback.asBinder());
873             }
874             sendCompleteMessage(onCompleteMessage, DataServiceCallback.RESULT_ERROR_ILLEGAL_STATE);
875         }
876     }
877 
878     /**
879      * Register for data call list changed event.
880      *
881      * @param h The target to post the event message to.
882      * @param what The event.
883      */
registerForDataCallListChanged(Handler h, int what)884     public void registerForDataCallListChanged(Handler h, int what) {
885         if (h != null) {
886             mDataCallListChangedRegistrants.addUnique(h, what, null);
887         }
888     }
889 
890     /**
891      * Unregister for data call list changed event.
892      *
893      * @param h The handler
894      */
unregisterForDataCallListChanged(Handler h)895     public void unregisterForDataCallListChanged(Handler h) {
896         if (h != null) {
897             mDataCallListChangedRegistrants.remove(h);
898         }
899     }
900 
901     /**
902      * Register apn unthrottled event
903      *
904      * @param h The target to post the event message to.
905      * @param what The event.
906      */
registerForApnUnthrottled(Handler h, int what)907     public void registerForApnUnthrottled(Handler h, int what) {
908         if (h != null) {
909             mApnUnthrottledRegistrants.addUnique(h, what, null);
910         }
911     }
912 
913     /**
914      * Unregister for apn unthrottled event
915      *
916      * @param h The handler
917      */
unregisterForApnUnthrottled(Handler h)918     public void unregisterForApnUnthrottled(Handler h) {
919         if (h != null) {
920             mApnUnthrottledRegistrants.remove(h);
921         }
922     }
923 
924     /**
925      * Register for data service binding status changed event.
926      *
927      * @param h The target to post the event message to.
928      * @param what The event.
929      * @param obj The user object.
930      */
registerForServiceBindingChanged(Handler h, int what, Object obj)931     public void registerForServiceBindingChanged(Handler h, int what, Object obj) {
932         if (h != null) {
933             mServiceBindingChangedRegistrants.addUnique(h, what, obj);
934         }
935 
936     }
937 
938     /**
939      * Unregister for data service binding status changed event.
940      *
941      * @param h The handler
942      */
unregisterForServiceBindingChanged(Handler h)943     public void unregisterForServiceBindingChanged(Handler h) {
944         if (h != null) {
945             mServiceBindingChangedRegistrants.remove(h);
946         }
947     }
948 
949     /**
950      * Get the transport type. Must be a {@link TransportType}.
951      *
952      * @return
953      */
954     @TransportType
getTransportType()955     public int getTransportType() {
956         return mTransportType;
957     }
958 
log(String s)959     private void log(String s) {
960         Rlog.d(mTag, s);
961     }
962 
loge(String s)963     private void loge(String s) {
964         Rlog.e(mTag, s);
965     }
966 }
967