• 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, mPhone.getCarrierId());
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.getAccessNetworksManager().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 
332         @Override
onApnUnthrottled(String apn)333         public void onApnUnthrottled(String apn) {
334             if (apn != null) {
335                 mApnUnthrottledRegistrants.notifyRegistrants(
336                         new AsyncResult(null, apn, null));
337             } else {
338                 loge("onApnUnthrottled: apn is null");
339             }
340         }
341 
342         @Override
onDataProfileUnthrottled(DataProfile dataProfile)343         public void onDataProfileUnthrottled(DataProfile dataProfile) {
344             if (dataProfile != null) {
345                 mApnUnthrottledRegistrants.notifyRegistrants(
346                         new AsyncResult(null, dataProfile, null));
347             } else {
348                 loge("onDataProfileUnthrottled: dataProfile is null");
349             }
350         }
351     }
352 
353     /**
354      * Constructor
355      *
356      * @param phone The phone object
357      * @param transportType The transport type
358      * @param tagSuffix Logging tag suffix
359      */
DataServiceManager(Phone phone, @TransportType int transportType, String tagSuffix)360     public DataServiceManager(Phone phone, @TransportType int transportType, String tagSuffix) {
361         mPhone = phone;
362         mTag = "DSM" + tagSuffix;
363         mTransportType = transportType;
364         mBound = false;
365         mCarrierConfigManager = (CarrierConfigManager) phone.getContext().getSystemService(
366                 Context.CARRIER_CONFIG_SERVICE);
367         // NOTE: Do NOT use AppGlobals to retrieve the permission manager; AppGlobals
368         // caches the service instance, but we need to explicitly request a new service
369         // so it can be mocked out for tests
370         mPermissionManager = (LegacyPermissionManager) phone.getContext().getSystemService(
371                 Context.LEGACY_PERMISSION_SERVICE);
372         mAppOps = (AppOpsManager) phone.getContext().getSystemService(Context.APP_OPS_SERVICE);
373 
374         IntentFilter intentFilter = new IntentFilter();
375         intentFilter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
376         try {
377             Context contextAsUser = phone.getContext().createPackageContextAsUser(
378                 phone.getContext().getPackageName(), 0, UserHandle.ALL);
379             contextAsUser.registerReceiver(mBroadcastReceiver, intentFilter,
380                 null /* broadcastPermission */, null);
381         } catch (PackageManager.NameNotFoundException e) {
382             loge("Package name not found: " + e.getMessage());
383         }
384 
385         PhoneConfigurationManager.registerForMultiSimConfigChange(
386                 this, EVENT_BIND_DATA_SERVICE, null);
387 
388         sendEmptyMessage(EVENT_BIND_DATA_SERVICE);
389     }
390 
391     /**
392      * Handle message events
393      *
394      * @param msg The message to handle
395      */
396     @Override
handleMessage(Message msg)397     public void handleMessage(Message msg) {
398         switch (msg.what) {
399             case EVENT_BIND_DATA_SERVICE:
400                 rebindDataService();
401                 break;
402             case EVENT_WATCHDOG_TIMEOUT:
403                 handleRequestUnresponded((CellularDataServiceCallback) msg.obj);
404                 break;
405             default:
406                 loge("Unhandled event " + msg.what);
407         }
408     }
409 
handleRequestUnresponded(CellularDataServiceCallback callback)410     private void handleRequestUnresponded(CellularDataServiceCallback callback) {
411         String message = "Request " + callback.getTag() + " unresponded on transport "
412                 + AccessNetworkConstants.transportTypeToString(mTransportType) + " in "
413                 + REQUEST_UNRESPONDED_TIMEOUT / 1000 + " seconds.";
414         log(message);
415         // Using fixed UUID to avoid duplicate bugreport notification
416         AnomalyReporter.reportAnomaly(
417                 UUID.fromString("f5d5cbe6-9bd6-4009-b764-42b1b649b1de"),
418                 message, mPhone.getCarrierId());
419     }
420 
unbindDataService()421     private void unbindDataService() {
422         // Start by cleaning up all packages that *shouldn't* have permissions.
423         revokePermissionsFromUnusedDataServices();
424         if (mIDataService != null && mIDataService.asBinder().isBinderAlive()) {
425             log("unbinding service");
426             // Remove the network availability updater and then unbind the service.
427             try {
428                 mIDataService.removeDataServiceProvider(mPhone.getPhoneId());
429             } catch (RemoteException e) {
430                 loge("Cannot remove data service provider. " + e);
431             }
432         }
433 
434         if (mServiceConnection != null) {
435             mPhone.getContext().unbindService(mServiceConnection);
436         }
437         mIDataService = null;
438         mServiceConnection = null;
439         mTargetBindingPackageName = null;
440         mBound = false;
441     }
442 
bindDataService(String packageName)443     private void bindDataService(String packageName) {
444         if (mPhone == null || !SubscriptionManager.isValidPhoneId(mPhone.getPhoneId())) {
445             loge("can't bindDataService with invalid phone or phoneId.");
446             return;
447         }
448 
449         if (TextUtils.isEmpty(packageName)) {
450             loge("Can't find the binding package");
451             return;
452         }
453 
454         Intent intent = null;
455         String className = getDataServiceClassName();
456         if (TextUtils.isEmpty(className)) {
457             intent = new Intent(DataService.SERVICE_INTERFACE);
458             intent.setPackage(packageName);
459         } else {
460             ComponentName cm = new ComponentName(packageName, className);
461             intent = new Intent(DataService.SERVICE_INTERFACE).setComponent(cm);
462         }
463 
464         // Then pre-emptively grant the permissions to the package we will bind.
465         grantPermissionsToService(packageName);
466 
467         try {
468             mServiceConnection = new CellularDataServiceConnection();
469             if (!mPhone.getContext().bindService(
470                     intent, mServiceConnection, Context.BIND_AUTO_CREATE)) {
471                 loge("Cannot bind to the data service.");
472                 return;
473             }
474             mTargetBindingPackageName = packageName;
475         } catch (Exception e) {
476             loge("Cannot bind to the data service. Exception: " + e);
477         }
478     }
479 
rebindDataService()480     private void rebindDataService() {
481         String packageName = getDataServicePackageName();
482         // Do nothing if no need to rebind.
483         if (SubscriptionManager.isValidPhoneId(mPhone.getPhoneId())
484                 && TextUtils.equals(packageName, mTargetBindingPackageName)) {
485             if (DBG) log("Service " + packageName + " already bound or being bound.");
486             return;
487         }
488 
489         unbindDataService();
490         bindDataService(packageName);
491     }
492 
493     @NonNull
getAllDataServicePackageNames()494     private Set<String> getAllDataServicePackageNames() {
495         // Cowardly using the public PackageManager interface here.
496         // Note: This matches only packages that were installed on the system image. If we ever
497         // expand the permissions model to allow CarrierPrivileged packages, then this will need
498         // to be updated.
499         List<ResolveInfo> dataPackages =
500                 mPhone.getContext().getPackageManager().queryIntentServices(
501                         new Intent(DataService.SERVICE_INTERFACE),
502                                 PackageManager.MATCH_SYSTEM_ONLY);
503         HashSet<String> packageNames = new HashSet<>();
504         for (ResolveInfo info : dataPackages) {
505             if (info.serviceInfo == null) continue;
506             packageNames.add(info.serviceInfo.packageName);
507         }
508         return packageNames;
509     }
510 
511     /**
512      * Get the data service package name for our current transport type.
513      *
514      * @return package name of the data service package for the the current transportType.
515      */
getDataServicePackageName()516     public String getDataServicePackageName() {
517         return getDataServicePackageName(mTransportType);
518     }
519 
520     /**
521      * Get the data service package by transport type.
522      *
523      * When we bind to a DataService package, we need to revoke permissions from stale
524      * packages; we need to exclude data packages for all transport types, so we need to
525      * to be able to query by transport type.
526      *
527      * @param transportType The transport type
528      * @return package name of the data service package for the specified transportType.
529      */
getDataServicePackageName(@ransportType int transportType)530     private String getDataServicePackageName(@TransportType int transportType) {
531         String packageName;
532         int resourceId;
533         String carrierConfig;
534 
535         switch (transportType) {
536             case AccessNetworkConstants.TRANSPORT_TYPE_WWAN:
537                 resourceId = com.android.internal.R.string.config_wwan_data_service_package;
538                 carrierConfig = CarrierConfigManager
539                         .KEY_CARRIER_DATA_SERVICE_WWAN_PACKAGE_OVERRIDE_STRING;
540                 break;
541             case AccessNetworkConstants.TRANSPORT_TYPE_WLAN:
542                 resourceId = com.android.internal.R.string.config_wlan_data_service_package;
543                 carrierConfig = CarrierConfigManager
544                         .KEY_CARRIER_DATA_SERVICE_WLAN_PACKAGE_OVERRIDE_STRING;
545                 break;
546             default:
547                 throw new IllegalStateException("Transport type not WWAN or WLAN. type="
548                         + AccessNetworkConstants.transportTypeToString(mTransportType));
549         }
550 
551         // Read package name from resource overlay
552         packageName = mPhone.getContext().getResources().getString(resourceId);
553 
554         PersistableBundle b = mCarrierConfigManager.getConfigForSubId(mPhone.getSubId());
555 
556         if (b != null && !TextUtils.isEmpty(b.getString(carrierConfig))) {
557             // If carrier config overrides it, use the one from carrier config
558             packageName = b.getString(carrierConfig, packageName);
559         }
560 
561         return packageName;
562     }
563 
564     /**
565      * Get the data service class name for our current transport type.
566      *
567      * @return class name of the data service package for the the current transportType.
568      */
getDataServiceClassName()569     private String getDataServiceClassName() {
570         return getDataServiceClassName(mTransportType);
571     }
572 
573 
574     /**
575      * Get the data service class by transport type.
576      *
577      * @param transportType either WWAN or WLAN
578      * @return class name of the data service package for the specified transportType.
579      */
getDataServiceClassName(int transportType)580     private String getDataServiceClassName(int transportType) {
581         String className;
582         int resourceId;
583         String carrierConfig;
584         switch (transportType) {
585             case AccessNetworkConstants.TRANSPORT_TYPE_WWAN:
586                 resourceId = com.android.internal.R.string.config_wwan_data_service_class;
587                 carrierConfig = CarrierConfigManager
588                         .KEY_CARRIER_DATA_SERVICE_WWAN_CLASS_OVERRIDE_STRING;
589                 break;
590             case AccessNetworkConstants.TRANSPORT_TYPE_WLAN:
591                 resourceId = com.android.internal.R.string.config_wlan_data_service_class;
592                 carrierConfig = CarrierConfigManager
593                         .KEY_CARRIER_DATA_SERVICE_WLAN_CLASS_OVERRIDE_STRING;
594                 break;
595             default:
596                 throw new IllegalStateException("Transport type not WWAN or WLAN. type="
597                         + transportType);
598         }
599 
600         // Read package name from resource overlay
601         className = mPhone.getContext().getResources().getString(resourceId);
602 
603         PersistableBundle b = mCarrierConfigManager.getConfigForSubId(mPhone.getSubId());
604 
605         if (b != null && !TextUtils.isEmpty(b.getString(carrierConfig))) {
606             // If carrier config overrides it, use the one from carrier config
607             className = b.getString(carrierConfig, className);
608         }
609 
610         return className;
611     }
612 
sendCompleteMessage(Message msg, @DataServiceCallback.ResultCode int code)613     private void sendCompleteMessage(Message msg, @DataServiceCallback.ResultCode int code) {
614         if (msg != null) {
615             msg.arg1 = code;
616             msg.sendToTarget();
617         }
618     }
619 
620     /**
621      * Setup a data connection. The data service provider must implement this method to support
622      * establishing a packet data connection. When completed or error, the service must invoke
623      * the provided callback to notify the platform.
624      *
625      * @param accessNetworkType Access network type that the data call will be established on.
626      *        Must be one of {@link AccessNetworkConstants.AccessNetworkType}.
627      * @param dataProfile Data profile used for data call setup. See {@link DataProfile}
628      * @param isRoaming True if the device is data roaming.
629      * @param allowRoaming True if data roaming is allowed by the user.
630      * @param reason The reason for data setup. Must be {@link DataService#REQUEST_REASON_NORMAL} or
631      *        {@link DataService#REQUEST_REASON_HANDOVER}.
632      * @param linkProperties If {@code reason} is {@link DataService#REQUEST_REASON_HANDOVER}, this
633      *        is the link properties of the existing data connection, otherwise null.
634      * @param pduSessionId The pdu session id to be used for this data call.  A value of -1 means
635      *                     no pdu session id was attached to this call.
636      *                     Reference: 3GPP TS 24.007 Section 11.2.3.1b
637      * @param sliceInfo The slice that represents S-NSSAI.
638      *                  Reference: 3GPP TS 24.501
639      * @param trafficDescriptor The traffic descriptor for this data call, used for URSP matching.
640      *                          Reference: 3GPP TS TS 24.526 Section 5.2
641      * @param matchAllRuleAllowed True if using the default match-all URSP rule for this request is
642      *                            allowed.
643      * @param onCompleteMessage The result message for this request. Null if the client does not
644      *        care about the result.
645      */
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)646     public void setupDataCall(int accessNetworkType, DataProfile dataProfile, boolean isRoaming,
647             boolean allowRoaming, int reason, LinkProperties linkProperties, int pduSessionId,
648             @Nullable NetworkSliceInfo sliceInfo, @Nullable TrafficDescriptor trafficDescriptor,
649             boolean matchAllRuleAllowed, Message onCompleteMessage) {
650         if (DBG) log("setupDataCall");
651         if (!mBound) {
652             loge("setupDataCall: Data service not bound.");
653             sendCompleteMessage(onCompleteMessage, DataServiceCallback.RESULT_ERROR_ILLEGAL_STATE);
654             return;
655         }
656 
657         CellularDataServiceCallback callback = new CellularDataServiceCallback("setupDataCall");
658         if (onCompleteMessage != null) {
659             mMessageMap.put(callback.asBinder(), onCompleteMessage);
660         }
661         try {
662             sendMessageDelayed(obtainMessage(EVENT_WATCHDOG_TIMEOUT, callback),
663                     REQUEST_UNRESPONDED_TIMEOUT);
664             mIDataService.setupDataCall(mPhone.getPhoneId(), accessNetworkType, dataProfile,
665                     isRoaming, allowRoaming, reason, linkProperties, pduSessionId, sliceInfo,
666                     trafficDescriptor, matchAllRuleAllowed, callback);
667         } catch (RemoteException e) {
668             loge("setupDataCall: Cannot invoke setupDataCall on data service.");
669             mMessageMap.remove(callback.asBinder());
670             sendCompleteMessage(onCompleteMessage, DataServiceCallback.RESULT_ERROR_ILLEGAL_STATE);
671         }
672     }
673 
674     /**
675      * Deactivate a data connection. The data service provider must implement this method to
676      * support data connection tear down. When completed or error, the service must invoke the
677      * provided callback to notify the platform.
678      *
679      * @param cid Call id returned in the callback of {@link #setupDataCall(int, DataProfile,
680      *        boolean, boolean, int, LinkProperties, Message)}
681      * @param reason The reason for data deactivation. Must be
682      *        {@link DataService#REQUEST_REASON_NORMAL}, {@link DataService#REQUEST_REASON_SHUTDOWN}
683      *        or {@link DataService#REQUEST_REASON_HANDOVER}.
684      * @param onCompleteMessage The result message for this request. Null if the client does not
685      *        care about the result.
686      */
deactivateDataCall(int cid, int reason, Message onCompleteMessage)687     public void deactivateDataCall(int cid, int reason, Message onCompleteMessage) {
688         if (DBG) log("deactivateDataCall");
689         if (!mBound) {
690             loge("Data service not bound.");
691             sendCompleteMessage(onCompleteMessage, DataServiceCallback.RESULT_ERROR_ILLEGAL_STATE);
692             return;
693         }
694 
695         CellularDataServiceCallback callback =
696                 new CellularDataServiceCallback("deactivateDataCall");
697         if (onCompleteMessage != null) {
698             mMessageMap.put(callback.asBinder(), onCompleteMessage);
699         }
700         try {
701             sendMessageDelayed(obtainMessage(EVENT_WATCHDOG_TIMEOUT, callback),
702                     REQUEST_UNRESPONDED_TIMEOUT);
703             mIDataService.deactivateDataCall(mPhone.getPhoneId(), cid, reason, callback);
704         } catch (RemoteException e) {
705             loge("Cannot invoke deactivateDataCall on data service.");
706             mMessageMap.remove(callback.asBinder());
707             sendCompleteMessage(onCompleteMessage, DataServiceCallback.RESULT_ERROR_ILLEGAL_STATE);
708         }
709     }
710 
711     /**
712      * Indicates that a handover has begun.  This is called on the source transport.
713      *
714      * Any resources being transferred cannot be released while a
715      * handover is underway.
716      *
717      * If a handover was unsuccessful, then the framework calls DataServiceManager#cancelHandover.
718      * The target transport retains ownership over any of the resources being transferred.
719      *
720      * If a handover was successful, the framework calls DataServiceManager#deactivateDataCall with
721      * reason HANDOVER. The target transport now owns the transferred resources and is
722      * responsible for releasing them.
723      *
724      * @param cid The identifier of the data call which is provided in DataCallResponse
725      * @param onCompleteMessage The result callback for this request.
726      */
startHandover(int cid, @NonNull Message onCompleteMessage)727     public void startHandover(int cid, @NonNull Message onCompleteMessage) {
728         CellularDataServiceCallback callback =
729                 setupCallbackHelper("startHandover", onCompleteMessage);
730         if (callback == null) {
731             loge("startHandover: callback == null");
732             sendCompleteMessage(onCompleteMessage, DataServiceCallback.RESULT_ERROR_ILLEGAL_STATE);
733             return;
734         }
735 
736         try {
737             sendMessageDelayed(obtainMessage(EVENT_WATCHDOG_TIMEOUT, callback),
738                     REQUEST_UNRESPONDED_TIMEOUT);
739             mIDataService.startHandover(mPhone.getPhoneId(), cid, callback);
740         } catch (RemoteException e) {
741             loge("Cannot invoke startHandover on data service.");
742             mMessageMap.remove(callback.asBinder());
743             sendCompleteMessage(onCompleteMessage, DataServiceCallback.RESULT_ERROR_ILLEGAL_STATE);
744         }
745     }
746 
747     /**
748      * Indicates that a handover was cancelled after a call to DataServiceManager#startHandover.
749      * This is called on the source transport.
750      *
751      * Since the handover was unsuccessful, the source transport retains ownership over any of
752      * the resources being transferred and is still responsible for releasing them.
753      *
754      * @param cid The identifier of the data call which is provided in DataCallResponse
755      * @param onCompleteMessage The result callback for this request.
756      */
cancelHandover(int cid, @NonNull Message onCompleteMessage)757     public void cancelHandover(int cid, @NonNull Message onCompleteMessage) {
758         CellularDataServiceCallback callback =
759                 setupCallbackHelper("cancelHandover", onCompleteMessage);
760         if (callback == null) {
761             sendCompleteMessage(onCompleteMessage, DataServiceCallback.RESULT_ERROR_ILLEGAL_STATE);
762             return;
763         }
764 
765         try {
766             sendMessageDelayed(obtainMessage(EVENT_WATCHDOG_TIMEOUT, callback),
767                     REQUEST_UNRESPONDED_TIMEOUT);
768             mIDataService.cancelHandover(mPhone.getPhoneId(), cid, callback);
769         } catch (RemoteException e) {
770             loge("Cannot invoke cancelHandover on data service.");
771             mMessageMap.remove(callback.asBinder());
772             sendCompleteMessage(onCompleteMessage, DataServiceCallback.RESULT_ERROR_ILLEGAL_STATE);
773         }
774     }
775 
776     @Nullable
setupCallbackHelper( @onNull final String operationName, @NonNull final Message onCompleteMessage)777     private CellularDataServiceCallback setupCallbackHelper(
778             @NonNull final String operationName, @NonNull final Message onCompleteMessage) {
779         if (DBG) log(operationName);
780         if (!mBound) {
781             sendCompleteMessage(onCompleteMessage, DataServiceCallback.RESULT_ERROR_ILLEGAL_STATE);
782             return null;
783         }
784 
785         CellularDataServiceCallback callback =
786                 new CellularDataServiceCallback(operationName);
787         if (onCompleteMessage != null) {
788             if (DBG) log(operationName + ": onCompleteMessage set");
789             mMessageMap.put(callback.asBinder(), onCompleteMessage);
790         } else {
791             if (DBG) log(operationName + ": onCompleteMessage not set");
792         }
793         return callback;
794     }
795 
796     /**
797      * Set an APN to initial attach network.
798      *
799      * @param dataProfile Data profile used for data call setup. See {@link DataProfile}.
800      * @param isRoaming True if the device is data roaming.
801      * @param onCompleteMessage The result message for this request. Null if the client does not
802      *        care about the result.
803      */
setInitialAttachApn(DataProfile dataProfile, boolean isRoaming, Message onCompleteMessage)804     public void setInitialAttachApn(DataProfile dataProfile, boolean isRoaming,
805                                     Message onCompleteMessage) {
806         if (DBG) log("setInitialAttachApn");
807         if (!mBound) {
808             loge("Data service not bound.");
809             sendCompleteMessage(onCompleteMessage, DataServiceCallback.RESULT_ERROR_ILLEGAL_STATE);
810             return;
811         }
812 
813         CellularDataServiceCallback callback =
814                 new CellularDataServiceCallback("setInitialAttachApn");
815         if (onCompleteMessage != null) {
816             mMessageMap.put(callback.asBinder(), onCompleteMessage);
817         }
818         try {
819             mIDataService.setInitialAttachApn(mPhone.getPhoneId(), dataProfile, isRoaming,
820                     callback);
821         } catch (RemoteException e) {
822             loge("Cannot invoke setInitialAttachApn on data service.");
823             mMessageMap.remove(callback.asBinder());
824             sendCompleteMessage(onCompleteMessage, DataServiceCallback.RESULT_ERROR_ILLEGAL_STATE);
825         }
826     }
827 
828     /**
829      * Send current carrier's data profiles to the data service for data call setup. This is
830      * only for CDMA carrier that can change the profile through OTA. The data service should
831      * always uses the latest data profile sent by the framework.
832      *
833      * @param dps A list of data profiles.
834      * @param isRoaming True if the device is data roaming.
835      * @param onCompleteMessage The result message for this request. Null if the client does not
836      *        care about the result.
837      */
setDataProfile(List<DataProfile> dps, boolean isRoaming, Message onCompleteMessage)838     public void setDataProfile(List<DataProfile> dps, boolean isRoaming,
839                                Message onCompleteMessage) {
840         if (DBG) log("setDataProfile");
841         if (!mBound) {
842             loge("Data service not bound.");
843             sendCompleteMessage(onCompleteMessage, DataServiceCallback.RESULT_ERROR_ILLEGAL_STATE);
844             return;
845         }
846 
847         CellularDataServiceCallback callback = new CellularDataServiceCallback("setDataProfile");
848         if (onCompleteMessage != null) {
849             mMessageMap.put(callback.asBinder(), onCompleteMessage);
850         }
851         try {
852             mIDataService.setDataProfile(mPhone.getPhoneId(), dps, isRoaming, callback);
853         } catch (RemoteException e) {
854             loge("Cannot invoke setDataProfile on data service.");
855             mMessageMap.remove(callback.asBinder());
856             sendCompleteMessage(onCompleteMessage, DataServiceCallback.RESULT_ERROR_ILLEGAL_STATE);
857         }
858     }
859 
860     /**
861      * Get the active data call list.
862      *
863      * @param onCompleteMessage The result message for this request. Null if the client does not
864      *        care about the result.
865      */
requestDataCallList(Message onCompleteMessage)866     public void requestDataCallList(Message onCompleteMessage) {
867         if (DBG) log("requestDataCallList");
868         if (!mBound) {
869             loge("Data service not bound.");
870             sendCompleteMessage(onCompleteMessage, DataServiceCallback.RESULT_ERROR_ILLEGAL_STATE);
871             return;
872         }
873 
874         CellularDataServiceCallback callback =
875                 new CellularDataServiceCallback("requestDataCallList");
876         if (onCompleteMessage != null) {
877             mMessageMap.put(callback.asBinder(), onCompleteMessage);
878         }
879         try {
880             mIDataService.requestDataCallList(mPhone.getPhoneId(), callback);
881         } catch (RemoteException e) {
882             loge("Cannot invoke requestDataCallList on data service.");
883             if (callback != null) {
884                 mMessageMap.remove(callback.asBinder());
885             }
886             sendCompleteMessage(onCompleteMessage, DataServiceCallback.RESULT_ERROR_ILLEGAL_STATE);
887         }
888     }
889 
890     /**
891      * Register for data call list changed event.
892      *
893      * @param h The target to post the event message to.
894      * @param what The event.
895      */
registerForDataCallListChanged(Handler h, int what)896     public void registerForDataCallListChanged(Handler h, int what) {
897         if (h != null) {
898             mDataCallListChangedRegistrants.addUnique(h, what, null);
899         }
900     }
901 
902     /**
903      * Unregister for data call list changed event.
904      *
905      * @param h The handler
906      */
unregisterForDataCallListChanged(Handler h)907     public void unregisterForDataCallListChanged(Handler h) {
908         if (h != null) {
909             mDataCallListChangedRegistrants.remove(h);
910         }
911     }
912 
913     /**
914      * Register apn unthrottled event
915      *
916      * @param h The target to post the event message to.
917      * @param what The event.
918      */
registerForApnUnthrottled(Handler h, int what)919     public void registerForApnUnthrottled(Handler h, int what) {
920         if (h != null) {
921             mApnUnthrottledRegistrants.addUnique(h, what, null);
922         }
923     }
924 
925     /**
926      * Unregister for apn unthrottled event
927      *
928      * @param h The handler
929      */
unregisterForApnUnthrottled(Handler h)930     public void unregisterForApnUnthrottled(Handler h) {
931         if (h != null) {
932             mApnUnthrottledRegistrants.remove(h);
933         }
934     }
935 
936     /**
937      * Register for data service binding status changed event.
938      *
939      * @param h The target to post the event message to.
940      * @param what The event.
941      * @param obj The user object.
942      */
registerForServiceBindingChanged(Handler h, int what, Object obj)943     public void registerForServiceBindingChanged(Handler h, int what, Object obj) {
944         if (h != null) {
945             mServiceBindingChangedRegistrants.addUnique(h, what, obj);
946         }
947 
948     }
949 
950     /**
951      * Unregister for data service binding status changed event.
952      *
953      * @param h The handler
954      */
unregisterForServiceBindingChanged(Handler h)955     public void unregisterForServiceBindingChanged(Handler h) {
956         if (h != null) {
957             mServiceBindingChangedRegistrants.remove(h);
958         }
959     }
960 
961     /**
962      * Get the transport type. Must be a {@link TransportType}.
963      *
964      * @return
965      */
966     @TransportType
getTransportType()967     public int getTransportType() {
968         return mTransportType;
969     }
970 
log(String s)971     private void log(String s) {
972         Rlog.d(mTag, s);
973     }
974 
loge(String s)975     private void loge(String s) {
976         Rlog.e(mTag, s);
977     }
978 }
979