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