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