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