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