• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 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.phone;
18 
19 import android.Manifest;
20 import android.app.compat.CompatChanges;
21 import android.compat.annotation.ChangeId;
22 import android.compat.annotation.EnabledAfter;
23 import android.content.pm.PackageManager;
24 import android.net.Uri;
25 import android.os.Binder;
26 import android.os.Build;
27 import android.os.RemoteException;
28 import android.os.ServiceSpecificException;
29 import android.os.UserHandle;
30 import android.telephony.SubscriptionManager;
31 import android.telephony.TelephonyFrameworkInitializer;
32 import android.telephony.ims.DelegateRequest;
33 import android.telephony.ims.ImsException;
34 import android.telephony.ims.RcsContactUceCapability;
35 import android.telephony.ims.RcsUceAdapter.PublishState;
36 import android.telephony.ims.RegistrationManager;
37 import android.telephony.ims.aidl.IImsCapabilityCallback;
38 import android.telephony.ims.aidl.IImsRcsController;
39 import android.telephony.ims.aidl.IImsRegistrationCallback;
40 import android.telephony.ims.aidl.IRcsUceControllerCallback;
41 import android.telephony.ims.aidl.IRcsUcePublishStateCallback;
42 import android.telephony.ims.aidl.ISipDelegate;
43 import android.telephony.ims.aidl.ISipDelegateConnectionStateCallback;
44 import android.telephony.ims.aidl.ISipDelegateMessageCallback;
45 import android.telephony.ims.feature.ImsFeature;
46 import android.telephony.ims.feature.RcsFeature;
47 import android.telephony.ims.stub.ImsRegistrationImplBase;
48 import android.util.Log;
49 
50 import com.android.ims.ImsManager;
51 import com.android.ims.internal.IImsServiceFeatureCallback;
52 import com.android.internal.telephony.IIntegerConsumer;
53 import com.android.internal.telephony.ISipDialogStateCallback;
54 import com.android.internal.telephony.Phone;
55 import com.android.internal.telephony.TelephonyPermissions;
56 import com.android.internal.telephony.ims.ImsResolver;
57 import com.android.services.telephony.rcs.RcsFeatureController;
58 import com.android.services.telephony.rcs.SipTransportController;
59 import com.android.services.telephony.rcs.TelephonyRcsService;
60 import com.android.services.telephony.rcs.UceControllerManager;
61 
62 import java.util.List;
63 import java.util.Set;
64 
65 /**
66  * Implementation of the IImsRcsController interface.
67  */
68 public class ImsRcsController extends IImsRcsController.Stub {
69     private static final String TAG = "ImsRcsController";
70 
71     /** The singleton instance. */
72     private static ImsRcsController sInstance;
73 
74     private PhoneGlobals mApp;
75     private TelephonyRcsService mRcsService;
76     private ImsResolver mImsResolver;
77     // set by shell cmd phone src set-device-enabled true/false
78     private Boolean mSingleRegistrationOverride;
79 
80     /**
81      * For apps targeting Android T and above, support the publishing state on APIs, such as
82      * {@code RcsUceAdapter#PUBLISH_STATE_PUBLISHING}
83      * @hide
84      */
85     @ChangeId
86     @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.S)
87     public static final long SUPPORT_PUBLISHING_STATE = 202894742;
88 
89     /**
90      * Initialize the singleton ImsRcsController instance.
91      * This is only done once, at startup, from PhoneApp.onCreate().
92      */
init(PhoneGlobals app)93     static ImsRcsController init(PhoneGlobals app) {
94         synchronized (ImsRcsController.class) {
95             if (sInstance == null) {
96                 sInstance = new ImsRcsController(app);
97             } else {
98                 Log.wtf(TAG, "init() called multiple times!  sInstance = " + sInstance);
99             }
100             return sInstance;
101         }
102     }
103 
104     /** Private constructor; @see init() */
ImsRcsController(PhoneGlobals app)105     private ImsRcsController(PhoneGlobals app) {
106         Log.i(TAG, "ImsRcsController");
107         mApp = app;
108         TelephonyFrameworkInitializer
109                 .getTelephonyServiceManager().getTelephonyImsServiceRegisterer().register(this);
110         mImsResolver = ImsResolver.getInstance();
111     }
112 
113     /**
114      * Register a {@link RegistrationManager.RegistrationCallback} to receive IMS network
115      * registration state.
116      */
117     @Override
registerImsRegistrationCallback(int subId, IImsRegistrationCallback callback)118     public void registerImsRegistrationCallback(int subId, IImsRegistrationCallback callback) {
119         TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
120                 mApp, subId, "registerImsRegistrationCallback");
121         final long token = Binder.clearCallingIdentity();
122         try {
123             getRcsFeatureController(subId).registerImsRegistrationCallback(subId, callback);
124         } catch (ImsException e) {
125             Log.e(TAG, "registerImsRegistrationCallback: sudId=" + subId + ", " + e.getMessage());
126             throw new ServiceSpecificException(e.getCode());
127         } finally {
128             Binder.restoreCallingIdentity(token);
129         }
130     }
131 
132     /**
133      * Removes an existing {@link RegistrationManager.RegistrationCallback}.
134      */
135     @Override
unregisterImsRegistrationCallback(int subId, IImsRegistrationCallback callback)136     public void unregisterImsRegistrationCallback(int subId, IImsRegistrationCallback callback) {
137         TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
138                 mApp, subId, "unregisterImsRegistrationCallback");
139         final long token = Binder.clearCallingIdentity();
140         try {
141             getRcsFeatureController(subId).unregisterImsRegistrationCallback(subId, callback);
142         } catch (ServiceSpecificException e) {
143             Log.e(TAG, "unregisterImsRegistrationCallback: error=" + e.errorCode);
144         } finally {
145             Binder.restoreCallingIdentity(token);
146         }
147     }
148 
149     /**
150      * Get the IMS service registration state for the RcsFeature associated with this sub id.
151      */
152     @Override
getImsRcsRegistrationState(int subId, IIntegerConsumer consumer)153     public void getImsRcsRegistrationState(int subId, IIntegerConsumer consumer) {
154         TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
155                 mApp, subId, "getImsRcsRegistrationState");
156         final long token = Binder.clearCallingIdentity();
157         try {
158             getRcsFeatureController(subId).getRegistrationState(regState -> {
159                 try {
160                     consumer.accept((regState == null)
161                             ? RegistrationManager.REGISTRATION_STATE_NOT_REGISTERED : regState);
162                 } catch (RemoteException e) {
163                     Log.w(TAG, "getImsRcsRegistrationState: callback is not available.");
164                 }
165             });
166         } finally {
167             Binder.restoreCallingIdentity(token);
168         }
169     }
170 
171     /**
172      * Gets the Transport Type associated with the current IMS RCS registration.
173      */
174     @Override
getImsRcsRegistrationTransportType(int subId, IIntegerConsumer consumer)175     public void getImsRcsRegistrationTransportType(int subId, IIntegerConsumer consumer) {
176         TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
177                 mApp, subId, "getImsRcsRegistrationTransportType");
178         final long token = Binder.clearCallingIdentity();
179         try {
180             getRcsFeatureController(subId).getRegistrationTech(regTech -> {
181                 // Convert registration tech from ImsRegistrationImplBase -> RegistrationManager
182                 int regTechConverted = (regTech == null)
183                         ? ImsRegistrationImplBase.REGISTRATION_TECH_NONE : regTech;
184                 regTechConverted = RegistrationManager.IMS_REG_TO_ACCESS_TYPE_MAP.get(
185                         regTechConverted);
186                 try {
187                     consumer.accept(regTechConverted);
188                 } catch (RemoteException e) {
189                     Log.w(TAG, "getImsRcsRegistrationTransportType: callback is not available.");
190                 }
191             });
192         } finally {
193             Binder.restoreCallingIdentity(token);
194         }
195     }
196 
197     /**
198      * Register a capability callback which will provide RCS availability updates for the
199      * subscription specified.
200      *
201      * @param subId the subscription ID
202      * @param callback The ImsCapabilityCallback to be registered.
203      */
204     @Override
registerRcsAvailabilityCallback(int subId, IImsCapabilityCallback callback)205     public void registerRcsAvailabilityCallback(int subId, IImsCapabilityCallback callback) {
206         enforceReadPrivilegedPermission("registerRcsAvailabilityCallback");
207         final long token = Binder.clearCallingIdentity();
208         try {
209             getRcsFeatureController(subId).registerRcsAvailabilityCallback(subId, callback);
210         } catch (ImsException e) {
211             Log.e(TAG, "registerRcsAvailabilityCallback: sudId=" + subId + ", " + e.getMessage());
212             throw new ServiceSpecificException(e.getCode());
213         } finally {
214             Binder.restoreCallingIdentity(token);
215         }
216     }
217 
218     /**
219      * Remove the registered capability callback.
220      *
221      * @param subId the subscription ID
222      * @param callback The ImsCapabilityCallback to be removed.
223      */
224     @Override
unregisterRcsAvailabilityCallback(int subId, IImsCapabilityCallback callback)225     public void unregisterRcsAvailabilityCallback(int subId, IImsCapabilityCallback callback) {
226         enforceReadPrivilegedPermission("unregisterRcsAvailabilityCallback");
227         final long token = Binder.clearCallingIdentity();
228         try {
229             getRcsFeatureController(subId).unregisterRcsAvailabilityCallback(subId, callback);
230         } catch (ServiceSpecificException e) {
231             Log.e(TAG, "unregisterRcsAvailabilityCallback: error=" + e.errorCode);
232         } finally {
233             Binder.restoreCallingIdentity(token);
234         }
235     }
236 
237     /**
238      * Query for the capability of an IMS RCS service
239      *
240      * @param subId the subscription ID
241      * @param capability the RCS capability to query.
242      * @param radioTech the radio technology type that we are querying.
243      * @return true if the RCS capability is capable for this subscription, false otherwise.
244      */
245     @Override
isCapable(int subId, @RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability, @ImsRegistrationImplBase.ImsRegistrationTech int radioTech)246     public boolean isCapable(int subId,
247             @RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability,
248             @ImsRegistrationImplBase.ImsRegistrationTech int radioTech) {
249         enforceReadPrivilegedPermission("isCapable");
250         final long token = Binder.clearCallingIdentity();
251         try {
252             return getRcsFeatureController(subId).isCapable(capability, radioTech);
253         } catch (ImsException e) {
254             Log.e(TAG, "isCapable: sudId=" + subId
255                     + ", capability=" + capability + ", " + e.getMessage());
256             throw new ServiceSpecificException(e.getCode(), e.getMessage());
257         } finally {
258             Binder.restoreCallingIdentity(token);
259         }
260     }
261 
262     /**
263      * Query the availability of an IMS RCS capability.
264      *
265      * @param subId the subscription ID
266      * @param capability the RCS capability to query.
267      * @return true if the RCS capability is currently available for the associated subscription,
268      * @param radioTech the radio technology type that we are querying.
269      * false otherwise.
270      */
271     @Override
isAvailable(int subId, @RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability, @ImsRegistrationImplBase.ImsRegistrationTech int radioTech)272     public boolean isAvailable(int subId,
273             @RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability,
274             @ImsRegistrationImplBase.ImsRegistrationTech int radioTech) {
275         enforceReadPrivilegedPermission("isAvailable");
276         final long token = Binder.clearCallingIdentity();
277         try {
278             return getRcsFeatureController(subId).isAvailable(capability, radioTech);
279         } catch (ImsException e) {
280             Log.e(TAG, "isAvailable: sudId=" + subId
281                     + ", capability=" + capability + ", " + e.getMessage());
282             throw new ServiceSpecificException(e.getCode(), e.getMessage());
283         } finally {
284             Binder.restoreCallingIdentity(token);
285         }
286     }
287 
288     @Override
requestCapabilities(int subId, String callingPackage, String callingFeatureId, List<Uri> contactNumbers, IRcsUceControllerCallback c)289     public void requestCapabilities(int subId, String callingPackage, String callingFeatureId,
290             List<Uri> contactNumbers, IRcsUceControllerCallback c) {
291         enforceAccessUserCapabilityExchangePermission("requestCapabilities");
292         enforceReadContactsPermission("requestCapabilities");
293         final long token = Binder.clearCallingIdentity();
294         try {
295             UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
296                     UceControllerManager.class);
297             if (uceCtrlManager == null) {
298                 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
299                         "This subscription does not support UCE.");
300             }
301             uceCtrlManager.requestCapabilities(contactNumbers, c);
302         } catch (ImsException e) {
303             throw new ServiceSpecificException(e.getCode(), e.getMessage());
304         } finally {
305             Binder.restoreCallingIdentity(token);
306         }
307     }
308 
309     @Override
requestAvailability(int subId, String callingPackage, String callingFeatureId, Uri contactNumber, IRcsUceControllerCallback c)310     public void requestAvailability(int subId, String callingPackage,
311             String callingFeatureId, Uri contactNumber, IRcsUceControllerCallback c) {
312         enforceAccessUserCapabilityExchangePermission("requestAvailability");
313         enforceReadContactsPermission("requestAvailability");
314         final long token = Binder.clearCallingIdentity();
315         try {
316             UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
317                     UceControllerManager.class);
318             if (uceCtrlManager == null) {
319                 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
320                         "This subscription does not support UCE.");
321             }
322             uceCtrlManager.requestNetworkAvailability(contactNumber, c);
323         } catch (ImsException e) {
324             throw new ServiceSpecificException(e.getCode(), e.getMessage());
325         } finally {
326             Binder.restoreCallingIdentity(token);
327         }
328     }
329 
330     @Override
getUcePublishState(int subId)331     public @PublishState int getUcePublishState(int subId) {
332         enforceReadPrivilegedPermission("getUcePublishState");
333         final int uid = Binder.getCallingUid();
334         final long token = Binder.clearCallingIdentity();
335         boolean isSupportPublishingState = false;
336         try {
337             UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
338                     UceControllerManager.class);
339             if (uceCtrlManager == null) {
340                 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
341                         "This subscription does not support UCE.");
342             }
343             if (CompatChanges.isChangeEnabled(SUPPORT_PUBLISHING_STATE, uid)) {
344                 isSupportPublishingState = true;
345             }
346             return uceCtrlManager.getUcePublishState(isSupportPublishingState);
347         } catch (ImsException e) {
348             throw new ServiceSpecificException(e.getCode(), e.getMessage());
349         } finally {
350             Binder.restoreCallingIdentity(token);
351         }
352     }
353 
354     /**
355      * Add new feature tags to the Set used to calculate the capabilities in PUBLISH.
356      */
357     // Used for SHELL command only right now.
addUceRegistrationOverrideShell(int subId, Set<String> featureTags)358     public RcsContactUceCapability addUceRegistrationOverrideShell(int subId,
359             Set<String> featureTags) throws ImsException {
360         // Permission check happening in PhoneInterfaceManager.
361         try {
362             UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
363                     UceControllerManager.class);
364             if (uceCtrlManager == null) {
365                 return null;
366             }
367             return uceCtrlManager.addUceRegistrationOverride(featureTags);
368         } catch (ServiceSpecificException e) {
369             throw new ImsException(e.getMessage(), e.errorCode);
370         }
371     }
372 
373     /**
374      * Remove existing feature tags to the Set used to calculate the capabilities in PUBLISH.
375      */
376     // Used for SHELL command only right now.
removeUceRegistrationOverrideShell(int subId, Set<String> featureTags)377     public RcsContactUceCapability removeUceRegistrationOverrideShell(int subId,
378             Set<String> featureTags) throws ImsException {
379         // Permission check happening in PhoneInterfaceManager.
380         try {
381             UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
382                     UceControllerManager.class);
383             if (uceCtrlManager == null) {
384                 return null;
385             }
386             return uceCtrlManager.removeUceRegistrationOverride(featureTags);
387         } catch (ServiceSpecificException e) {
388             throw new ImsException(e.getMessage(), e.errorCode);
389         }
390     }
391 
392     /**
393      * Clear all overrides in the Set used to calculate the capabilities in PUBLISH.
394      */
395     // Used for SHELL command only right now.
clearUceRegistrationOverrideShell(int subId)396     public RcsContactUceCapability clearUceRegistrationOverrideShell(int subId)
397             throws ImsException {
398         try {
399             // Permission check happening in PhoneInterfaceManager.
400             UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
401                     UceControllerManager.class);
402             if (uceCtrlManager == null) {
403                 return null;
404             }
405             return uceCtrlManager.clearUceRegistrationOverride();
406         } catch (ServiceSpecificException e) {
407             throw new ImsException(e.getMessage(), e.errorCode);
408         }
409     }
410 
411     /**
412      * @return current RcsContactUceCapability instance that will be used for PUBLISH.
413      */
414     // Used for SHELL command only right now.
getLatestRcsContactUceCapabilityShell(int subId)415     public RcsContactUceCapability getLatestRcsContactUceCapabilityShell(int subId)
416             throws ImsException {
417         try {
418             // Permission check happening in PhoneInterfaceManager.
419             UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
420                     UceControllerManager.class);
421             if (uceCtrlManager == null) {
422                 return null;
423             }
424             return uceCtrlManager.getLatestRcsContactUceCapability();
425         } catch (ServiceSpecificException e) {
426             throw new ImsException(e.getMessage(), e.errorCode);
427         }
428     }
429 
430     /**
431      * @return the PIDf XML used in the last PUBLISH procedure or "none" if the device is not
432      * published. Returns {@code null} if the operation failed due to an error.
433      */
434     // Used for SHELL command only right now.
getLastUcePidfXmlShell(int subId)435     public String getLastUcePidfXmlShell(int subId) throws ImsException {
436         try {
437             // Permission check happening in PhoneInterfaceManager.
438             UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
439                     UceControllerManager.class);
440             if (uceCtrlManager == null) {
441                 return null;
442             }
443             String pidfXml = uceCtrlManager.getLastPidfXml();
444             return pidfXml == null ? "none" : pidfXml;
445         } catch (ServiceSpecificException e) {
446             throw new ImsException(e.getMessage(), e.errorCode);
447         }
448     }
449 
450     /**
451      * Remove UCE requests cannot be sent to the network status.
452      * @return true if this command is successful.
453      */
454     // Used for SHELL command only right now.
removeUceRequestDisallowedStatus(int subId)455     public boolean removeUceRequestDisallowedStatus(int subId) throws ImsException {
456         try {
457             UceControllerManager uceCtrlManager = getRcsFeatureController(subId, true).getFeature(
458                     UceControllerManager.class);
459             if (uceCtrlManager == null) {
460                 return false;
461             }
462             return uceCtrlManager.removeUceRequestDisallowedStatus();
463         } catch (ServiceSpecificException e) {
464             throw new ImsException(e.getMessage(), e.errorCode);
465         }
466     }
467 
468     /**
469      * Set the timeout for contact capabilities request.
470      */
471     // Used for SHELL command only right now.
setCapabilitiesRequestTimeout(int subId, long timeoutAfter)472     public boolean setCapabilitiesRequestTimeout(int subId, long timeoutAfter) throws ImsException {
473         try {
474             UceControllerManager uceCtrlManager = getRcsFeatureController(subId, true).getFeature(
475                     UceControllerManager.class);
476             if (uceCtrlManager == null) {
477                 return false;
478             }
479             return uceCtrlManager.setCapabilitiesRequestTimeout(timeoutAfter);
480         } catch (ServiceSpecificException e) {
481             throw new ImsException(e.getMessage(), e.errorCode);
482         }
483     }
484 
485     @Override
registerUcePublishStateCallback(int subId, IRcsUcePublishStateCallback c)486     public void registerUcePublishStateCallback(int subId, IRcsUcePublishStateCallback c) {
487         enforceReadPrivilegedPermission("registerUcePublishStateCallback");
488         final int uid = Binder.getCallingUid();
489         final long token = Binder.clearCallingIdentity();
490         boolean isSupportPublishingState = false;
491         try {
492             UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
493                     UceControllerManager.class);
494             if (uceCtrlManager == null) {
495                 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
496                         "This subscription does not support UCE.");
497             }
498 
499             if (CompatChanges.isChangeEnabled(SUPPORT_PUBLISHING_STATE, uid)) {
500                 isSupportPublishingState = true;
501             }
502             uceCtrlManager.registerPublishStateCallback(c, isSupportPublishingState);
503         } catch (ImsException e) {
504             throw new ServiceSpecificException(e.getCode(), e.getMessage());
505         } finally {
506             Binder.restoreCallingIdentity(token);
507         }
508     }
509 
510     @Override
unregisterUcePublishStateCallback(int subId, IRcsUcePublishStateCallback c)511     public void unregisterUcePublishStateCallback(int subId, IRcsUcePublishStateCallback c) {
512         enforceReadPrivilegedPermission("unregisterUcePublishStateCallback");
513         final long token = Binder.clearCallingIdentity();
514         try {
515             UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
516                     UceControllerManager.class);
517             if (uceCtrlManager == null) {
518                 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
519                         "This subscription does not support UCE.");
520             }
521             uceCtrlManager.unregisterPublishStateCallback(c);
522         } catch (ServiceSpecificException e) {
523             Log.e(TAG, "unregisterUcePublishStateCallback: error=" + e.errorCode);
524         } finally {
525             Binder.restoreCallingIdentity(token);
526         }
527     }
528 
529     @Override
isUceSettingEnabled(int subId, String callingPackage, String callingFeatureId)530     public boolean isUceSettingEnabled(int subId, String callingPackage, String callingFeatureId) {
531         if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
532                 mApp, subId, callingPackage, callingFeatureId, "isUceSettingEnabled")) {
533             Log.w(TAG, "isUceSettingEnabled: READ_PHONE_STATE app op disabled when accessing "
534                     + "isUceSettingEnabled");
535             return false;
536         }
537         final long token = Binder.clearCallingIdentity();
538         try {
539             return SubscriptionManager.getBooleanSubscriptionProperty(subId,
540                     SubscriptionManager.IMS_RCS_UCE_ENABLED, false /*defaultValue*/, mApp);
541         } finally {
542             Binder.restoreCallingIdentity(token);
543         }
544     }
545 
546     @Override
setUceSettingEnabled(int subId, boolean isEnabled)547     public void setUceSettingEnabled(int subId, boolean isEnabled) {
548         enforceModifyPermission();
549         final long token = Binder.clearCallingIdentity();
550         try {
551             SubscriptionManager.setSubscriptionProperty(subId,
552                     SubscriptionManager.IMS_RCS_UCE_ENABLED, (isEnabled ? "1" : "0"));
553         } finally {
554             Binder.restoreCallingIdentity(token);
555         }
556     }
557 
558     @Override
isSipDelegateSupported(int subId)559     public boolean isSipDelegateSupported(int subId) {
560         TelephonyPermissions.enforceAnyPermissionGranted(mApp, Binder.getCallingUid(),
561                 "isSipDelegateSupported",
562                 Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION,
563                 Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
564         if (!isImsSingleRegistrationSupportedOnDevice()) {
565             return false;
566         }
567         final long token = Binder.clearCallingIdentity();
568         try {
569             SipTransportController transport = getRcsFeatureController(subId).getFeature(
570                     SipTransportController.class);
571             if (transport == null) {
572                 return false;
573             }
574             return transport.isSupported(subId);
575         } catch (ImsException e) {
576             throw new ServiceSpecificException(e.getCode(), e.getMessage());
577         } catch (ServiceSpecificException e) {
578             if (e.errorCode == ImsException.CODE_ERROR_UNSUPPORTED_OPERATION) {
579                 return false;
580             }
581             throw e;
582         } finally {
583             Binder.restoreCallingIdentity(token);
584         }
585     }
586 
587     @Override
createSipDelegate(int subId, DelegateRequest request, String packageName, ISipDelegateConnectionStateCallback delegateState, ISipDelegateMessageCallback delegateMessage)588     public void createSipDelegate(int subId, DelegateRequest request, String packageName,
589             ISipDelegateConnectionStateCallback delegateState,
590             ISipDelegateMessageCallback delegateMessage) {
591         enforceImsSingleRegistrationPermission("createSipDelegate");
592         if (!isImsSingleRegistrationSupportedOnDevice()) {
593             throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
594                     "SipDelegate creation is only supported for devices supporting IMS single "
595                             + "registration");
596         }
597         if (!UserHandle.getUserHandleForUid(Binder.getCallingUid()).isSystem()) {
598             throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
599                     "SipDelegate creation is only available to primary user.");
600         }
601         try {
602             int remoteUid = mApp.getPackageManager().getPackageUid(packageName, 0 /*flags*/);
603             if (Binder.getCallingUid() != remoteUid) {
604                 throw new SecurityException("passed in packageName does not match the caller");
605             }
606         } catch (PackageManager.NameNotFoundException e) {
607             throw new SecurityException("Passed in PackageName can not be found on device");
608         }
609 
610         final int uid = Binder.getCallingUid();
611         final long identity = Binder.clearCallingIdentity();
612         SipTransportController transport = getRcsFeatureController(subId).getFeature(
613                 SipTransportController.class);
614         if (transport == null) {
615             throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
616                     "This subscription does not support the creation of SIP delegates");
617         }
618         try {
619             transport.createSipDelegate(subId, uid, request, packageName, delegateState,
620                     delegateMessage);
621         } catch (ImsException e) {
622             throw new ServiceSpecificException(e.getCode(), e.getMessage());
623         } finally {
624             Binder.restoreCallingIdentity(identity);
625         }
626     }
627 
628     @Override
destroySipDelegate(int subId, ISipDelegate connection, int reason)629     public void destroySipDelegate(int subId, ISipDelegate connection, int reason) {
630         // Do not check permissions here - the caller needs to have a connection already from the
631         // create method to call this method.
632         if (connection == null) {
633             return;
634         }
635         final long identity = Binder.clearCallingIdentity();
636         try {
637             SipTransportController transport = getRcsFeatureController(subId).getFeature(
638                     SipTransportController.class);
639             if (transport == null) {
640                 return;
641             }
642             transport.destroySipDelegate(subId, connection, reason);
643         } catch (ServiceSpecificException e) {
644             Log.e(TAG, "destroySipDelegate: error=" + e.errorCode);
645         } finally {
646             Binder.restoreCallingIdentity(identity);
647         }
648     }
649 
650     @Override
triggerNetworkRegistration(int subId, ISipDelegate connection, int sipCode, String sipReason)651     public void triggerNetworkRegistration(int subId, ISipDelegate connection, int sipCode,
652             String sipReason) {
653         enforceImsSingleRegistrationPermission("triggerNetworkRegistration");
654 
655         final long identity = Binder.clearCallingIdentity();
656         try {
657             SipTransportController transport = getRcsFeatureController(subId).getFeature(
658                     SipTransportController.class);
659             if (transport == null) {
660                 return;
661             }
662             transport.triggerFullNetworkRegistration(subId, connection, sipCode, sipReason);
663         } catch (ServiceSpecificException e) {
664             Log.e(TAG, "triggerNetworkRegistration: error=" + e.errorCode);
665         } finally {
666             Binder.restoreCallingIdentity(identity);
667         }
668     }
669 
670     /**
671      * Register a state of Sip Dialog callback
672      */
673     @Override
registerSipDialogStateCallback(int subId, ISipDialogStateCallback cb)674     public void registerSipDialogStateCallback(int subId, ISipDialogStateCallback cb) {
675         enforceReadPrivilegedPermission("registerSipDialogStateCallback");
676         if (cb == null) {
677             throw new IllegalArgumentException("SipDialogStateCallback is null");
678         }
679         final long identity = Binder.clearCallingIdentity();
680         if (!SubscriptionManager.isValidSubscriptionId(subId)) {
681             throw new IllegalArgumentException("Invalid Subscription ID: " + subId);
682         }
683         try {
684             SipTransportController transport = getRcsFeatureController(subId).getFeature(
685                     SipTransportController.class);
686             if (transport == null) {
687                 throw new ServiceSpecificException(ImsException.CODE_ERROR_SERVICE_UNAVAILABLE,
688                         "This transport does not support the registerSipDialogStateCallback"
689                                 + " of SIP delegates");
690             }
691             transport.addCallbackForSipDialogState(subId, cb);
692         } finally {
693             Binder.restoreCallingIdentity(identity);
694         }
695     }
696 
697     /**
698      * Unregister a state of Sip Dialog callback
699      */
700     @Override
unregisterSipDialogStateCallback(int subId, ISipDialogStateCallback cb)701     public  void unregisterSipDialogStateCallback(int subId, ISipDialogStateCallback cb) {
702         enforceReadPrivilegedPermission("unregisterSipDialogStateCallback");
703         if (cb == null) {
704             throw new IllegalArgumentException("SipDialogStateCallback is null");
705         }
706         final long identity = Binder.clearCallingIdentity();
707         if (!SubscriptionManager.isValidSubscriptionId(subId)) {
708             throw new IllegalArgumentException("Invalid Subscription ID: " + subId);
709         }
710         try {
711             SipTransportController transport = getRcsFeatureController(subId).getFeature(
712                     SipTransportController.class);
713             if (transport == null) {
714                 throw new ServiceSpecificException(ImsException.CODE_ERROR_SERVICE_UNAVAILABLE,
715                         "This transport does not support the unregisterSipDialogStateCallback"
716                                 + " of SIP delegates");
717             }
718             transport.removeCallbackForSipDialogState(subId, cb);
719         } finally {
720             Binder.restoreCallingIdentity(identity);
721         }
722     }
723 
724     /**
725      * Registers for updates to the RcsFeature connection through the IImsServiceFeatureCallback
726      * callback.
727      */
728     @Override
registerRcsFeatureCallback(int slotId, IImsServiceFeatureCallback callback)729     public void registerRcsFeatureCallback(int slotId, IImsServiceFeatureCallback callback) {
730         enforceModifyPermission();
731 
732         final long identity = Binder.clearCallingIdentity();
733         try {
734             if (mImsResolver == null) {
735                 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
736                         "Device does not support IMS");
737             }
738             mImsResolver.listenForFeature(slotId, ImsFeature.FEATURE_RCS, callback);
739         } finally {
740             Binder.restoreCallingIdentity(identity);
741         }
742     }
743 
744     /**
745      * Unregister a previously registered IImsServiceFeatureCallback associated with an ImsFeature.
746      */
747     @Override
unregisterImsFeatureCallback(IImsServiceFeatureCallback callback)748     public void unregisterImsFeatureCallback(IImsServiceFeatureCallback callback) {
749         enforceModifyPermission();
750 
751         final long identity = Binder.clearCallingIdentity();
752         try {
753             if (mImsResolver == null) return;
754             mImsResolver.unregisterImsFeatureCallback(callback);
755         } finally {
756             Binder.restoreCallingIdentity(identity);
757         }
758     }
759 
760     /**
761      * Make sure either called from same process as self (phone) or IPC caller has read privilege.
762      *
763      * @throws SecurityException if the caller does not have the required permission
764      */
enforceReadPrivilegedPermission(String message)765     private void enforceReadPrivilegedPermission(String message) {
766         mApp.enforceCallingOrSelfPermission(
767                 android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, message);
768     }
769 
770     /**
771      * @throws SecurityException if the caller does not have the required
772      *     PERFORM_IMS_SINGLE_REGISTRATION permission.
773      */
enforceImsSingleRegistrationPermission(String message)774     private void enforceImsSingleRegistrationPermission(String message) {
775         mApp.enforceCallingOrSelfPermission(
776                 Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION, message);
777     }
778 
779     /**
780      * Make sure the caller has the MODIFY_PHONE_STATE permission.
781      *
782      * @throws SecurityException if the caller does not have the required permission
783      */
enforceModifyPermission()784     private void enforceModifyPermission() {
785         mApp.enforceCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE, null);
786     }
787 
788     /**
789      * Make sure the caller has the ACCESS_RCS_USER_CAPABILITY_EXCHANGE permission.
790      *
791      * @throws SecurityException if the caller does not have the required permission.
792      */
enforceAccessUserCapabilityExchangePermission(String message)793     private void enforceAccessUserCapabilityExchangePermission(String message) {
794         mApp.enforceCallingOrSelfPermission(
795                 android.Manifest.permission.ACCESS_RCS_USER_CAPABILITY_EXCHANGE, message);
796     }
797 
798     /**
799      * Make sure the caller has the READ_CONTACTS permission.
800      *
801      * @throws SecurityException if the caller does not have the required permission.
802      */
enforceReadContactsPermission(String message)803     private void enforceReadContactsPermission(String message) {
804         mApp.enforceCallingOrSelfPermission(
805                 android.Manifest.permission.READ_CONTACTS, message);
806     }
807 
808     /**
809      * Retrieve RcsFeatureManager instance.
810      *
811      * @param subId the subscription ID
812      * @return The RcsFeatureManager instance
813      * @throws ServiceSpecificException if getting RcsFeatureManager instance failed.
814      */
getRcsFeatureController(int subId)815     private RcsFeatureController getRcsFeatureController(int subId) {
816         return getRcsFeatureController(subId, false /* skipVerifyingConfig */);
817     }
818 
819     /**
820      * Retrieve RcsFeatureManager instance.
821      *
822      * @param subId the subscription ID
823      * @param skipVerifyingConfig If the RCS configuration can be skip.
824      * @return The RcsFeatureManager instance
825      * @throws ServiceSpecificException if getting RcsFeatureManager instance failed.
826      */
getRcsFeatureController(int subId, boolean skipVerifyingConfig)827     private RcsFeatureController getRcsFeatureController(int subId, boolean skipVerifyingConfig) {
828         if (!ImsManager.isImsSupportedOnDevice(mApp)) {
829             throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
830                     "IMS is not available on device.");
831         }
832         if (mRcsService == null) {
833             throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
834                     "IMS is not available on device.");
835         }
836         Phone phone = PhoneGlobals.getPhone(subId);
837         if (phone == null) {
838             throw new ServiceSpecificException(ImsException.CODE_ERROR_INVALID_SUBSCRIPTION,
839                     "Invalid subscription Id: " + subId);
840         }
841         int slotId = phone.getPhoneId();
842         if (!skipVerifyingConfig) {
843             verifyImsRcsConfiguredOrThrow(slotId);
844             verifyRcsSubIdActiveOrThrow(slotId, subId);
845         }
846         RcsFeatureController c = mRcsService.getFeatureController(slotId);
847         if (c == null) {
848             // If we hit this case, we have verified that TelephonyRcsService has processed any
849             // subId changes for the associated slot and applied configs. In this case, the configs
850             // do not have the RCS feature enabled.
851             throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
852                     "The requested operation is not supported for subId " + subId);
853         }
854         if (!skipVerifyingConfig && c.getAssociatedSubId() != subId) {
855             // If we hit this case, the ImsFeature has not finished setting up the RCS feature yet
856             // or the RCS feature has crashed and is being set up again.
857             Log.w(TAG, "getRcsFeatureController: service unavailable on slot " + slotId
858                     + " for subId " + subId);
859             throw new ServiceSpecificException(ImsException.CODE_ERROR_SERVICE_UNAVAILABLE,
860                     "The ImsService is not currently available for subid " + subId
861                             + ", please try again");
862         }
863         return c;
864     }
865 
866     /**
867      * Ensure the TelephonyRcsService is tracking the supplied subId for the supplied slotId and has
868      * set up the stack.
869      */
verifyRcsSubIdActiveOrThrow(int slotId, int subId)870     private void verifyRcsSubIdActiveOrThrow(int slotId, int subId) {
871         if (mRcsService.verifyActiveSubId(slotId, subId)) return;
872 
873         Log.w(TAG, "verifyRcsSubIdActiveOrThrow: verify failed, service not set up yet on "
874                 + "slot " + slotId + " for subId " + subId);
875         throw new ServiceSpecificException(ImsException.CODE_ERROR_SERVICE_UNAVAILABLE,
876                 "ImsService set up in progress for subId " + subId
877                         + ", please try again");
878     }
879 
880     /**
881      * Throw an ImsException if the IMS resolver does not have an ImsService configured for RCS
882      * for the given slot ID or no ImsResolver instance has been created.
883      * @param slotId The slot ID that the IMS service is created for.
884      * @throws ServiceSpecificException If there is no ImsService configured for this slot.
885      */
verifyImsRcsConfiguredOrThrow(int slotId)886     private void verifyImsRcsConfiguredOrThrow(int slotId) {
887         if (mImsResolver == null
888                 || !mImsResolver.isImsServiceConfiguredForFeature(slotId, ImsFeature.FEATURE_RCS)) {
889             throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
890                     "This subscription does not support RCS");
891         }
892     }
893 
isImsSingleRegistrationSupportedOnDevice()894     private boolean isImsSingleRegistrationSupportedOnDevice() {
895         return mSingleRegistrationOverride != null ? mSingleRegistrationOverride
896                 : mApp.getPackageManager().hasSystemFeature(
897                         PackageManager.FEATURE_TELEPHONY_IMS_SINGLE_REGISTRATION);
898     }
899 
setRcsService(TelephonyRcsService rcsService)900     void setRcsService(TelephonyRcsService rcsService) {
901         mRcsService = rcsService;
902     }
903 
904     /**
905      * Override device RCS single registration support check for CTS testing or remove override
906      * if the Boolean is set to null.
907      */
setDeviceSingleRegistrationSupportOverride(Boolean deviceOverrideValue)908     void setDeviceSingleRegistrationSupportOverride(Boolean deviceOverrideValue) {
909         mSingleRegistrationOverride = deviceOverrideValue;
910     }
911 }
912