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