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