blob: d4a0f1ef17da1da49517ad8afdeb0635a6a6f529 [file] [log] [blame]
James.cf Linaf3183c2019-10-24 00:59:00 +08001/*
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
17package com.android.phone;
18
Brad Ebinger4df7e242021-02-17 23:23:21 +000019import android.Manifest;
Hyunho8ea90f32021-11-16 08:53:02 +000020import android.app.compat.CompatChanges;
21import android.compat.annotation.ChangeId;
22import android.compat.annotation.EnabledAfter;
Brad Ebinger63b6f5a2020-10-27 11:43:35 -070023import android.content.pm.PackageManager;
James.cf Linaf3183c2019-10-24 00:59:00 +080024import android.net.Uri;
James.cf Lincad981c2019-12-10 20:37:56 +080025import android.os.Binder;
Hyunho8ea90f32021-11-16 08:53:02 +000026import android.os.Build;
James.cf Lincad981c2019-12-10 20:37:56 +080027import android.os.RemoteException;
James.cf Lincad981c2019-12-10 20:37:56 +080028import android.os.ServiceSpecificException;
Brad Ebinger63b6f5a2020-10-27 11:43:35 -070029import android.os.UserHandle;
Brad Ebingerb7a866a2020-01-22 17:51:55 -080030import android.telephony.SubscriptionManager;
Peter Wangc035ce42020-01-08 21:00:22 -080031import android.telephony.TelephonyFrameworkInitializer;
Brad Ebingeraf1e9832020-10-14 10:49:28 -070032import android.telephony.ims.DelegateRequest;
James.cf Lincad981c2019-12-10 20:37:56 +080033import android.telephony.ims.ImsException;
Brad Ebingerd4c5bde2021-02-12 06:18:28 +000034import android.telephony.ims.RcsContactUceCapability;
James.cf Lin99a360d2020-11-04 10:48:37 +080035import android.telephony.ims.RcsUceAdapter.PublishState;
James.cf Lindc2d5422019-12-31 14:40:25 +080036import android.telephony.ims.RegistrationManager;
James.cf Linaf3183c2019-10-24 00:59:00 +080037import android.telephony.ims.aidl.IImsCapabilityCallback;
38import android.telephony.ims.aidl.IImsRcsController;
James.cf Lindc2d5422019-12-31 14:40:25 +080039import android.telephony.ims.aidl.IImsRegistrationCallback;
James.cf Linaf3183c2019-10-24 00:59:00 +080040import android.telephony.ims.aidl.IRcsUceControllerCallback;
James.cf Lincdad3862020-02-25 15:55:03 +080041import android.telephony.ims.aidl.IRcsUcePublishStateCallback;
Brad Ebingeraf1e9832020-10-14 10:49:28 -070042import android.telephony.ims.aidl.ISipDelegate;
43import android.telephony.ims.aidl.ISipDelegateConnectionStateCallback;
44import android.telephony.ims.aidl.ISipDelegateMessageCallback;
Brad Ebingere3ae65a2020-09-11 12:45:11 -070045import android.telephony.ims.feature.ImsFeature;
James.cf Linaf3183c2019-10-24 00:59:00 +080046import android.telephony.ims.feature.RcsFeature;
James.cf Lincad981c2019-12-10 20:37:56 +080047import android.telephony.ims.stub.ImsRegistrationImplBase;
James.cf Linaf3183c2019-10-24 00:59:00 +080048import android.util.Log;
49
James.cf Lindc2d5422019-12-31 14:40:25 +080050import com.android.ims.ImsManager;
Brad Ebingere3ae65a2020-09-11 12:45:11 -070051import com.android.ims.internal.IImsServiceFeatureCallback;
James.cf Lindc2d5422019-12-31 14:40:25 +080052import com.android.internal.telephony.IIntegerConsumer;
James.cf Lincad981c2019-12-10 20:37:56 +080053import com.android.internal.telephony.Phone;
Brad Ebinger8b79edc2020-02-27 19:13:24 -080054import com.android.internal.telephony.TelephonyPermissions;
Brad Ebingere3ae65a2020-09-11 12:45:11 -070055import com.android.internal.telephony.ims.ImsResolver;
Brad Ebingera68a4972020-01-30 17:31:23 -080056import com.android.services.telephony.rcs.RcsFeatureController;
Brad Ebingerb989c7c2020-09-23 17:03:48 -070057import com.android.services.telephony.rcs.SipTransportController;
James.cf Linc9f35a42020-01-15 02:35:22 +080058import com.android.services.telephony.rcs.TelephonyRcsService;
James.cf Lin99a360d2020-11-04 10:48:37 +080059import com.android.services.telephony.rcs.UceControllerManager;
James.cf Lincad981c2019-12-10 20:37:56 +080060
James.cf Linaf3183c2019-10-24 00:59:00 +080061import java.util.List;
Brad Ebingerd4c5bde2021-02-12 06:18:28 +000062import java.util.Set;
James.cf Linaf3183c2019-10-24 00:59:00 +080063
64/**
65 * Implementation of the IImsRcsController interface.
66 */
67public 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;
James.cf Linc9f35a42020-01-15 02:35:22 +080074 private TelephonyRcsService mRcsService;
Brad Ebingere3ae65a2020-09-11 12:45:11 -070075 private ImsResolver mImsResolver;
Brad Ebinger49a72b42021-01-29 00:55:24 +000076 // set by shell cmd phone src set-device-enabled true/false
77 private Boolean mSingleRegistrationOverride;
James.cf Linaf3183c2019-10-24 00:59:00 +080078
79 /**
Hyunho8ea90f32021-11-16 08:53:02 +000080 * 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 /**
James.cf Linaf3183c2019-10-24 00:59:00 +080089 * Initialize the singleton ImsRcsController instance.
90 * This is only done once, at startup, from PhoneApp.onCreate().
91 */
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() */
104 private ImsRcsController(PhoneGlobals app) {
105 Log.i(TAG, "ImsRcsController");
106 mApp = app;
Peter Wangc035ce42020-01-08 21:00:22 -0800107 TelephonyFrameworkInitializer
108 .getTelephonyServiceManager().getTelephonyImsServiceRegisterer().register(this);
Brad Ebingerd1947d82021-05-17 20:54:49 +0000109 mImsResolver = ImsResolver.getInstance();
James.cf Linaf3183c2019-10-24 00:59:00 +0800110 }
111
James.cf Lincad981c2019-12-10 20:37:56 +0800112 /**
Brad Ebingera68a4972020-01-30 17:31:23 -0800113 * Register a {@link RegistrationManager.RegistrationCallback} to receive IMS network
114 * registration state.
James.cf Lindc2d5422019-12-31 14:40:25 +0800115 */
116 @Override
Brad Ebingera68a4972020-01-30 17:31:23 -0800117 public void registerImsRegistrationCallback(int subId, IImsRegistrationCallback callback) {
Nathan Harold75a9ff12021-04-06 11:26:02 -0700118 TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
James.cf Linf020d162021-01-31 22:15:52 +0800119 mApp, subId, "registerImsRegistrationCallback");
James.cf Lindc2d5422019-12-31 14:40:25 +0800120 final long token = Binder.clearCallingIdentity();
121 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800122 getRcsFeatureController(subId).registerImsRegistrationCallback(subId, callback);
123 } catch (ImsException e) {
James.cf Lindc2d5422019-12-31 14:40:25 +0800124 Log.e(TAG, "registerImsRegistrationCallback: sudId=" + subId + ", " + e.getMessage());
125 throw new ServiceSpecificException(e.getCode());
126 } finally {
127 Binder.restoreCallingIdentity(token);
128 }
129 }
130
131 /**
Brad Ebingera68a4972020-01-30 17:31:23 -0800132 * Removes an existing {@link RegistrationManager.RegistrationCallback}.
James.cf Lindc2d5422019-12-31 14:40:25 +0800133 */
134 @Override
135 public void unregisterImsRegistrationCallback(int subId, IImsRegistrationCallback callback) {
Nathan Harold75a9ff12021-04-06 11:26:02 -0700136 TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
James.cf Linf020d162021-01-31 22:15:52 +0800137 mApp, subId, "unregisterImsRegistrationCallback");
James.cf Lindc2d5422019-12-31 14:40:25 +0800138 final long token = Binder.clearCallingIdentity();
139 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800140 getRcsFeatureController(subId).unregisterImsRegistrationCallback(subId, callback);
James.cf Lindc2d5422019-12-31 14:40:25 +0800141 } 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
152 public void getImsRcsRegistrationState(int subId, IIntegerConsumer consumer) {
Nathan Harold75a9ff12021-04-06 11:26:02 -0700153 TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
James.cf Linf020d162021-01-31 22:15:52 +0800154 mApp, subId, "getImsRcsRegistrationState");
James.cf Lindc2d5422019-12-31 14:40:25 +0800155 final long token = Binder.clearCallingIdentity();
156 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800157 getRcsFeatureController(subId).getRegistrationState(regState -> {
James.cf Lindc2d5422019-12-31 14:40:25 +0800158 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
174 public void getImsRcsRegistrationTransportType(int subId, IIntegerConsumer consumer) {
Nathan Harold75a9ff12021-04-06 11:26:02 -0700175 TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
James.cf Linf020d162021-01-31 22:15:52 +0800176 mApp, subId, "getImsRcsRegistrationTransportType");
James.cf Lindc2d5422019-12-31 14:40:25 +0800177 final long token = Binder.clearCallingIdentity();
178 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800179 getRcsFeatureController(subId).getRegistrationTech(regTech -> {
James.cf Lindc2d5422019-12-31 14:40:25 +0800180 // 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 /**
James.cf Lincad981c2019-12-10 20:37:56 +0800197 * 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 */
James.cf Linaf3183c2019-10-24 00:59:00 +0800203 @Override
Brad Ebingera68a4972020-01-30 17:31:23 -0800204 public void registerRcsAvailabilityCallback(int subId, IImsCapabilityCallback callback) {
James.cf Linaf3183c2019-10-24 00:59:00 +0800205 enforceReadPrivilegedPermission("registerRcsAvailabilityCallback");
James.cf Lincad981c2019-12-10 20:37:56 +0800206 final long token = Binder.clearCallingIdentity();
207 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800208 getRcsFeatureController(subId).registerRcsAvailabilityCallback(subId, callback);
209 } catch (ImsException e) {
James.cf Lincad981c2019-12-10 20:37:56 +0800210 Log.e(TAG, "registerRcsAvailabilityCallback: sudId=" + subId + ", " + e.getMessage());
211 throw new ServiceSpecificException(e.getCode());
212 } finally {
213 Binder.restoreCallingIdentity(token);
214 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800215 }
216
James.cf Lincad981c2019-12-10 20:37:56 +0800217 /**
218 * Remove the registered capability callback.
219 *
220 * @param subId the subscription ID
221 * @param callback The ImsCapabilityCallback to be removed.
222 */
James.cf Linaf3183c2019-10-24 00:59:00 +0800223 @Override
James.cf Lincad981c2019-12-10 20:37:56 +0800224 public void unregisterRcsAvailabilityCallback(int subId, IImsCapabilityCallback callback) {
James.cf Linaf3183c2019-10-24 00:59:00 +0800225 enforceReadPrivilegedPermission("unregisterRcsAvailabilityCallback");
James.cf Lincad981c2019-12-10 20:37:56 +0800226 final long token = Binder.clearCallingIdentity();
227 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800228 getRcsFeatureController(subId).unregisterRcsAvailabilityCallback(subId, callback);
Brad Ebinger919631e2021-06-02 17:46:35 -0700229 } catch (ServiceSpecificException e) {
230 Log.e(TAG, "unregisterRcsAvailabilityCallback: error=" + e.errorCode);
James.cf Lincad981c2019-12-10 20:37:56 +0800231 } finally {
232 Binder.restoreCallingIdentity(token);
233 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800234 }
235
James.cf Lincad981c2019-12-10 20:37:56 +0800236 /**
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.
James.cf Linf020d162021-01-31 22:15:52 +0800241 * @param radioTech the radio technology type that we are querying.
James.cf Lincad981c2019-12-10 20:37:56 +0800242 * @return true if the RCS capability is capable for this subscription, false otherwise.
243 */
James.cf Linaf3183c2019-10-24 00:59:00 +0800244 @Override
245 public boolean isCapable(int subId,
James.cf Lincad981c2019-12-10 20:37:56 +0800246 @RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability,
247 @ImsRegistrationImplBase.ImsRegistrationTech int radioTech) {
James.cf Linaf3183c2019-10-24 00:59:00 +0800248 enforceReadPrivilegedPermission("isCapable");
James.cf Lincad981c2019-12-10 20:37:56 +0800249 final long token = Binder.clearCallingIdentity();
250 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800251 return getRcsFeatureController(subId).isCapable(capability, radioTech);
252 } catch (ImsException e) {
James.cf Lincad981c2019-12-10 20:37:56 +0800253 Log.e(TAG, "isCapable: sudId=" + subId
254 + ", capability=" + capability + ", " + e.getMessage());
Brad Ebingere3885b22022-02-16 13:18:59 -0800255 throw new ServiceSpecificException(e.getCode(), e.getMessage());
James.cf Lincad981c2019-12-10 20:37:56 +0800256 } finally {
257 Binder.restoreCallingIdentity(token);
258 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800259 }
260
James.cf Lincad981c2019-12-10 20:37:56 +0800261 /**
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,
James.cf Linf020d162021-01-31 22:15:52 +0800267 * @param radioTech the radio technology type that we are querying.
James.cf Lincad981c2019-12-10 20:37:56 +0800268 * false otherwise.
269 */
James.cf Linaf3183c2019-10-24 00:59:00 +0800270 @Override
271 public boolean isAvailable(int subId,
James.cf Linf020d162021-01-31 22:15:52 +0800272 @RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability,
273 @ImsRegistrationImplBase.ImsRegistrationTech int radioTech) {
James.cf Linaf3183c2019-10-24 00:59:00 +0800274 enforceReadPrivilegedPermission("isAvailable");
James.cf Lincad981c2019-12-10 20:37:56 +0800275 final long token = Binder.clearCallingIdentity();
276 try {
James.cf Linf020d162021-01-31 22:15:52 +0800277 return getRcsFeatureController(subId).isAvailable(capability, radioTech);
Brad Ebingera68a4972020-01-30 17:31:23 -0800278 } catch (ImsException e) {
James.cf Lincad981c2019-12-10 20:37:56 +0800279 Log.e(TAG, "isAvailable: sudId=" + subId
280 + ", capability=" + capability + ", " + e.getMessage());
Brad Ebingere3885b22022-02-16 13:18:59 -0800281 throw new ServiceSpecificException(e.getCode(), e.getMessage());
James.cf Lincad981c2019-12-10 20:37:56 +0800282 } finally {
283 Binder.restoreCallingIdentity(token);
284 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800285 }
286
287 @Override
Brad Ebinger8b79edc2020-02-27 19:13:24 -0800288 public void requestCapabilities(int subId, String callingPackage, String callingFeatureId,
289 List<Uri> contactNumbers, IRcsUceControllerCallback c) {
James.cf Lin051dd252021-01-21 03:30:54 +0800290 enforceAccessUserCapabilityExchangePermission("requestCapabilities");
291 enforceReadContactsPermission("requestCapabilities");
Brad Ebingera68a4972020-01-30 17:31:23 -0800292 final long token = Binder.clearCallingIdentity();
293 try {
James.cf Lin99a360d2020-11-04 10:48:37 +0800294 UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
295 UceControllerManager.class);
296 if (uceCtrlManager == null) {
Brad Ebingera68a4972020-01-30 17:31:23 -0800297 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
298 "This subscription does not support UCE.");
299 }
James.cf Lin99a360d2020-11-04 10:48:37 +0800300 uceCtrlManager.requestCapabilities(contactNumbers, c);
301 } catch (ImsException e) {
302 throw new ServiceSpecificException(e.getCode(), e.getMessage());
Brad Ebingera68a4972020-01-30 17:31:23 -0800303 } finally {
304 Binder.restoreCallingIdentity(token);
Brad Ebinger1aa94992020-01-22 14:17:23 -0800305 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800306 }
307
308 @Override
James.cf Linbcdf8b32021-01-14 16:44:13 +0800309 public void requestAvailability(int subId, String callingPackage,
James.cf Lin64e91212020-10-30 01:09:52 +0800310 String callingFeatureId, Uri contactNumber, IRcsUceControllerCallback c) {
James.cf Lin051dd252021-01-21 03:30:54 +0800311 enforceAccessUserCapabilityExchangePermission("requestAvailability");
312 enforceReadContactsPermission("requestAvailability");
Brad Ebingera68a4972020-01-30 17:31:23 -0800313 final long token = Binder.clearCallingIdentity();
314 try {
James.cf Lin99a360d2020-11-04 10:48:37 +0800315 UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
316 UceControllerManager.class);
317 if (uceCtrlManager == null) {
Brad Ebingera68a4972020-01-30 17:31:23 -0800318 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
319 "This subscription does not support UCE.");
320 }
James.cf Lin99a360d2020-11-04 10:48:37 +0800321 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
330 public @PublishState int getUcePublishState(int subId) {
331 enforceReadPrivilegedPermission("getUcePublishState");
Hyunho8ea90f32021-11-16 08:53:02 +0000332 final int uid = Binder.getCallingUid();
James.cf Lin99a360d2020-11-04 10:48:37 +0800333 final long token = Binder.clearCallingIdentity();
Hyunho8ea90f32021-11-16 08:53:02 +0000334 boolean isSupportPublishingState = false;
James.cf Lin99a360d2020-11-04 10:48:37 +0800335 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 }
Hyunho8ea90f32021-11-16 08:53:02 +0000342 if (CompatChanges.isChangeEnabled(SUPPORT_PUBLISHING_STATE, uid)) {
343 isSupportPublishingState = true;
344 }
345 return uceCtrlManager.getUcePublishState(isSupportPublishingState);
James.cf Lin99a360d2020-11-04 10:48:37 +0800346 } catch (ImsException e) {
347 throw new ServiceSpecificException(e.getCode(), e.getMessage());
348 } finally {
349 Binder.restoreCallingIdentity(token);
350 }
351 }
352
Brad Ebingerd4c5bde2021-02-12 06:18:28 +0000353 /**
354 * Add new feature tags to the Set used to calculate the capabilities in PUBLISH.
355 */
356 // Used for SHELL command only right now.
357 public RcsContactUceCapability addUceRegistrationOverrideShell(int subId,
358 Set<String> featureTags) throws ImsException {
359 // Permission check happening in PhoneInterfaceManager.
Brad Ebinger919631e2021-06-02 17:46:35 -0700360 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);
Brad Ebingerd4c5bde2021-02-12 06:18:28 +0000369 }
Brad Ebingerd4c5bde2021-02-12 06:18:28 +0000370 }
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.
376 public RcsContactUceCapability removeUceRegistrationOverrideShell(int subId,
377 Set<String> featureTags) throws ImsException {
378 // Permission check happening in PhoneInterfaceManager.
Brad Ebinger919631e2021-06-02 17:46:35 -0700379 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);
Brad Ebingerd4c5bde2021-02-12 06:18:28 +0000388 }
Brad Ebingerd4c5bde2021-02-12 06:18:28 +0000389 }
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.
395 public RcsContactUceCapability clearUceRegistrationOverrideShell(int subId)
396 throws ImsException {
Brad Ebinger919631e2021-06-02 17:46:35 -0700397 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);
Brad Ebingerd4c5bde2021-02-12 06:18:28 +0000407 }
Brad Ebingerd4c5bde2021-02-12 06:18:28 +0000408 }
409
410 /**
411 * @return current RcsContactUceCapability instance that will be used for PUBLISH.
412 */
413 // Used for SHELL command only right now.
414 public RcsContactUceCapability getLatestRcsContactUceCapabilityShell(int subId)
415 throws ImsException {
Brad Ebinger919631e2021-06-02 17:46:35 -0700416 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);
Brad Ebingerd4c5bde2021-02-12 06:18:28 +0000426 }
Brad Ebingerd4c5bde2021-02-12 06:18:28 +0000427 }
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.
434 public String getLastUcePidfXmlShell(int subId) throws ImsException {
Brad Ebinger919631e2021-06-02 17:46:35 -0700435 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);
Brad Ebingerd4c5bde2021-02-12 06:18:28 +0000446 }
Brad Ebingerd4c5bde2021-02-12 06:18:28 +0000447 }
448
James.cf Line8713a42021-04-29 16:04:26 +0800449 /**
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.
454 public boolean removeUceRequestDisallowedStatus(int subId) throws ImsException {
Brad Ebinger919631e2021-06-02 17:46:35 -0700455 try {
James.cf Linc6b449f2021-06-05 01:11:15 +0800456 UceControllerManager uceCtrlManager = getRcsFeatureController(subId, true).getFeature(
Brad Ebinger919631e2021-06-02 17:46:35 -0700457 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);
James.cf Line8713a42021-04-29 16:04:26 +0800464 }
James.cf Line8713a42021-04-29 16:04:26 +0800465 }
466
James.cf Lin0fc71b02021-05-25 01:37:38 +0800467 /**
468 * Set the timeout for contact capabilities request.
469 */
470 // Used for SHELL command only right now.
471 public boolean setCapabilitiesRequestTimeout(int subId, long timeoutAfter) throws ImsException {
Brad Ebinger919631e2021-06-02 17:46:35 -0700472 try {
James.cf Linc6b449f2021-06-05 01:11:15 +0800473 UceControllerManager uceCtrlManager = getRcsFeatureController(subId, true).getFeature(
Brad Ebinger919631e2021-06-02 17:46:35 -0700474 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);
James.cf Lin0fc71b02021-05-25 01:37:38 +0800481 }
James.cf Lin0fc71b02021-05-25 01:37:38 +0800482 }
483
James.cf Lin99a360d2020-11-04 10:48:37 +0800484 @Override
485 public void registerUcePublishStateCallback(int subId, IRcsUcePublishStateCallback c) {
486 enforceReadPrivilegedPermission("registerUcePublishStateCallback");
Hyunho8ea90f32021-11-16 08:53:02 +0000487 final int uid = Binder.getCallingUid();
James.cf Lin99a360d2020-11-04 10:48:37 +0800488 final long token = Binder.clearCallingIdentity();
Hyunho8ea90f32021-11-16 08:53:02 +0000489 boolean isSupportPublishingState = false;
James.cf Lin99a360d2020-11-04 10:48:37 +0800490 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 }
Hyunho8ea90f32021-11-16 08:53:02 +0000497
498 if (CompatChanges.isChangeEnabled(SUPPORT_PUBLISHING_STATE, uid)) {
499 isSupportPublishingState = true;
500 }
501 uceCtrlManager.registerPublishStateCallback(c, isSupportPublishingState);
James.cf Lin99a360d2020-11-04 10:48:37 +0800502 } catch (ImsException e) {
503 throw new ServiceSpecificException(e.getCode(), e.getMessage());
504 } finally {
505 Binder.restoreCallingIdentity(token);
506 }
507 }
508
509 @Override
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);
Brad Ebinger919631e2021-06-02 17:46:35 -0700521 } catch (ServiceSpecificException e) {
522 Log.e(TAG, "unregisterUcePublishStateCallback: error=" + e.errorCode);
Brad Ebingera68a4972020-01-30 17:31:23 -0800523 } finally {
524 Binder.restoreCallingIdentity(token);
Brad Ebinger1aa94992020-01-22 14:17:23 -0800525 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800526 }
527
528 @Override
Brad Ebinger8b79edc2020-02-27 19:13:24 -0800529 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 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800543 }
544
545 @Override
546 public void setUceSettingEnabled(int subId, boolean isEnabled) {
547 enforceModifyPermission();
Brad Ebinger8b79edc2020-02-27 19:13:24 -0800548 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 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800555 }
556
Brad Ebingerb989c7c2020-09-23 17:03:48 -0700557 @Override
558 public boolean isSipDelegateSupported(int subId) {
Brad Ebinger4df7e242021-02-17 23:23:21 +0000559 TelephonyPermissions.enforceAnyPermissionGranted(mApp, Binder.getCallingUid(),
560 "isSipDelegateSupported",
561 Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION,
562 Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
Brad Ebinger49a72b42021-01-29 00:55:24 +0000563 if (!isImsSingleRegistrationSupportedOnDevice()) {
564 return false;
565 }
Brad Ebingerb989c7c2020-09-23 17:03:48 -0700566 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
Brad Ebingeraf1e9832020-10-14 10:49:28 -0700586 @Override
Brad Ebinger63b6f5a2020-10-27 11:43:35 -0700587 public void createSipDelegate(int subId, DelegateRequest request, String packageName,
Brad Ebingeraf1e9832020-10-14 10:49:28 -0700588 ISipDelegateConnectionStateCallback delegateState,
589 ISipDelegateMessageCallback delegateMessage) {
Brad Ebinger4df7e242021-02-17 23:23:21 +0000590 enforceImsSingleRegistrationPermission("createSipDelegate");
Brad Ebinger49a72b42021-01-29 00:55:24 +0000591 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 }
Brad Ebinger63b6f5a2020-10-27 11:43:35 -0700596 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 }
Brad Ebingeraf1e9832020-10-14 10:49:28 -0700608
Jinyoung Jeongca77e1c2021-10-21 04:34:46 +0000609 final int uid = Binder.getCallingUid();
Brad Ebingeraf1e9832020-10-14 10:49:28 -0700610 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 {
Jinyoung Jeongca77e1c2021-10-21 04:34:46 +0000618 transport.createSipDelegate(subId, uid, request, packageName, delegateState,
Brad Ebinger63b6f5a2020-10-27 11:43:35 -0700619 delegateMessage);
Brad Ebingeraf1e9832020-10-14 10:49:28 -0700620 } catch (ImsException e) {
621 throw new ServiceSpecificException(e.getCode(), e.getMessage());
622 } finally {
623 Binder.restoreCallingIdentity(identity);
624 }
625 }
626
627 @Override
628 public void destroySipDelegate(int subId, ISipDelegate connection, int reason) {
Brad Ebinger652411e2021-06-30 09:30:35 -0700629 // 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 }
Brad Ebingeraf1e9832020-10-14 10:49:28 -0700634 final long identity = Binder.clearCallingIdentity();
635 try {
Brad Ebinger63b6f5a2020-10-27 11:43:35 -0700636 SipTransportController transport = getRcsFeatureController(subId).getFeature(
637 SipTransportController.class);
638 if (transport == null) {
639 return;
640 }
641 transport.destroySipDelegate(subId, connection, reason);
Brad Ebinger919631e2021-06-02 17:46:35 -0700642 } catch (ServiceSpecificException e) {
643 Log.e(TAG, "destroySipDelegate: error=" + e.errorCode);
Brad Ebingeraf1e9832020-10-14 10:49:28 -0700644 } finally {
645 Binder.restoreCallingIdentity(identity);
646 }
647 }
648
Brad Ebinger36221382020-12-09 00:33:39 +0000649 @Override
650 public void triggerNetworkRegistration(int subId, ISipDelegate connection, int sipCode,
651 String sipReason) {
Brad Ebinger4df7e242021-02-17 23:23:21 +0000652 enforceImsSingleRegistrationPermission("triggerNetworkRegistration");
Brad Ebinger36221382020-12-09 00:33:39 +0000653
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);
Brad Ebinger919631e2021-06-02 17:46:35 -0700662 } catch (ServiceSpecificException e) {
663 Log.e(TAG, "triggerNetworkRegistration: error=" + e.errorCode);
Brad Ebinger36221382020-12-09 00:33:39 +0000664 } finally {
665 Binder.restoreCallingIdentity(identity);
666 }
667 }
668
James.cf Linaf3183c2019-10-24 00:59:00 +0800669 /**
Brad Ebingere3ae65a2020-09-11 12:45:11 -0700670 * Registers for updates to the RcsFeature connection through the IImsServiceFeatureCallback
671 * callback.
672 */
673 @Override
Brad Ebinger6366ce92020-10-01 13:51:05 -0700674 public void registerRcsFeatureCallback(int slotId, IImsServiceFeatureCallback callback) {
Brad Ebingere3ae65a2020-09-11 12:45:11 -0700675 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 }
Brad Ebinger6366ce92020-10-01 13:51:05 -0700683 mImsResolver.listenForFeature(slotId, ImsFeature.FEATURE_RCS, callback);
Brad Ebingere3ae65a2020-09-11 12:45:11 -0700684 } finally {
685 Binder.restoreCallingIdentity(identity);
686 }
687 }
Brad Ebinger6366ce92020-10-01 13:51:05 -0700688
Brad Ebingere3ae65a2020-09-11 12:45:11 -0700689 /**
690 * Unregister a previously registered IImsServiceFeatureCallback associated with an ImsFeature.
691 */
692 @Override
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 /**
James.cf Linaf3183c2019-10-24 00:59:00 +0800706 * 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 */
710 private void enforceReadPrivilegedPermission(String message) {
711 mApp.enforceCallingOrSelfPermission(
712 android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, message);
713 }
714
715 /**
Brad Ebinger4df7e242021-02-17 23:23:21 +0000716 * @throws SecurityException if the caller does not have the required
717 * PERFORM_IMS_SINGLE_REGISTRATION permission.
718 */
719 private void enforceImsSingleRegistrationPermission(String message) {
720 mApp.enforceCallingOrSelfPermission(
721 Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION, message);
722 }
723
724 /**
James.cf Linaf3183c2019-10-24 00:59:00 +0800725 * Make sure the caller has the MODIFY_PHONE_STATE permission.
726 *
727 * @throws SecurityException if the caller does not have the required permission
728 */
729 private void enforceModifyPermission() {
730 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE, null);
731 }
James.cf Lincad981c2019-12-10 20:37:56 +0800732
733 /**
James.cf Lin051dd252021-01-21 03:30:54 +0800734 * 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 */
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 */
748 private void enforceReadContactsPermission(String message) {
749 mApp.enforceCallingOrSelfPermission(
750 android.Manifest.permission.READ_CONTACTS, message);
751 }
752
753 /**
James.cf Lindc2d5422019-12-31 14:40:25 +0800754 * Retrieve RcsFeatureManager instance.
755 *
756 * @param subId the subscription ID
757 * @return The RcsFeatureManager instance
758 * @throws ServiceSpecificException if getting RcsFeatureManager instance failed.
759 */
Brad Ebingera68a4972020-01-30 17:31:23 -0800760 private RcsFeatureController getRcsFeatureController(int subId) {
James.cf Linc6b449f2021-06-05 01:11:15 +0800761 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 */
772 private RcsFeatureController getRcsFeatureController(int subId, boolean skipVerifyingConfig) {
James.cf Lindc2d5422019-12-31 14:40:25 +0800773 if (!ImsManager.isImsSupportedOnDevice(mApp)) {
James.cf Lincad981c2019-12-10 20:37:56 +0800774 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
James.cf Lindc2d5422019-12-31 14:40:25 +0800775 "IMS is not available on device.");
776 }
Brad Ebingera68a4972020-01-30 17:31:23 -0800777 if (mRcsService == null) {
778 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
779 "IMS is not available on device.");
780 }
James.cf Lindc2d5422019-12-31 14:40:25 +0800781 Phone phone = PhoneGlobals.getPhone(subId);
782 if (phone == null) {
783 throw new ServiceSpecificException(ImsException.CODE_ERROR_INVALID_SUBSCRIPTION,
784 "Invalid subscription Id: " + subId);
785 }
Brad Ebingera68a4972020-01-30 17:31:23 -0800786 int slotId = phone.getPhoneId();
James.cf Linc6b449f2021-06-05 01:11:15 +0800787 if (!skipVerifyingConfig) {
788 verifyImsRcsConfiguredOrThrow(slotId);
Brad Ebingere3885b22022-02-16 13:18:59 -0800789 verifyRcsSubIdActiveOrThrow(slotId, subId);
James.cf Linc6b449f2021-06-05 01:11:15 +0800790 }
Brad Ebingera68a4972020-01-30 17:31:23 -0800791 RcsFeatureController c = mRcsService.getFeatureController(slotId);
792 if (c == null) {
Brad Ebingere3885b22022-02-16 13:18:59 -0800793 // If we hit this case, we have verified that TelephonyRcsService has processed any
794 // subId changes for the associated slot and applied configs. In this case, the configs
795 // do not have the RCS feature enabled.
Brad Ebinger036dc9e2020-02-06 15:49:06 -0800796 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
797 "The requested operation is not supported for subId " + subId);
James.cf Lincad981c2019-12-10 20:37:56 +0800798 }
Brad Ebingere3885b22022-02-16 13:18:59 -0800799 if (!skipVerifyingConfig && c.getAssociatedSubId() != subId) {
800 // If we hit this case, the ImsFeature has not finished setting up the RCS feature yet
801 // or the RCS feature has crashed and is being set up again.
802 Log.w(TAG, "getRcsFeatureController: service unavailable on slot " + slotId
803 + " for subId " + subId);
804 throw new ServiceSpecificException(ImsException.CODE_ERROR_SERVICE_UNAVAILABLE,
805 "The ImsService is not currently available for subid " + subId
806 + ", please try again");
807 }
Brad Ebingera68a4972020-01-30 17:31:23 -0800808 return c;
James.cf Lincad981c2019-12-10 20:37:56 +0800809 }
James.cf Linc9f35a42020-01-15 02:35:22 +0800810
Brad Ebinger919631e2021-06-02 17:46:35 -0700811 /**
Brad Ebingere3885b22022-02-16 13:18:59 -0800812 * Ensure the TelephonyRcsService is tracking the supplied subId for the supplied slotId and has
813 * set up the stack.
814 */
815 private void verifyRcsSubIdActiveOrThrow(int slotId, int subId) {
816 if (mRcsService.verifyActiveSubId(slotId, subId)) return;
817
818 Log.w(TAG, "verifyRcsSubIdActiveOrThrow: verify failed, service not set up yet on "
819 + "slot " + slotId + " for subId " + subId);
820 throw new ServiceSpecificException(ImsException.CODE_ERROR_SERVICE_UNAVAILABLE,
821 "ImsService set up in progress for subId " + subId
822 + ", please try again");
823 }
824
825 /**
Brad Ebinger919631e2021-06-02 17:46:35 -0700826 * Throw an ImsException if the IMS resolver does not have an ImsService configured for RCS
827 * for the given slot ID or no ImsResolver instance has been created.
828 * @param slotId The slot ID that the IMS service is created for.
829 * @throws ServiceSpecificException If there is no ImsService configured for this slot.
830 */
831 private void verifyImsRcsConfiguredOrThrow(int slotId) {
832 if (mImsResolver == null
833 || !mImsResolver.isImsServiceConfiguredForFeature(slotId, ImsFeature.FEATURE_RCS)) {
834 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
835 "This subscription does not support RCS");
836 }
837 }
838
Brad Ebinger49a72b42021-01-29 00:55:24 +0000839 private boolean isImsSingleRegistrationSupportedOnDevice() {
840 return mSingleRegistrationOverride != null ? mSingleRegistrationOverride
841 : mApp.getPackageManager().hasSystemFeature(
842 PackageManager.FEATURE_TELEPHONY_IMS_SINGLE_REGISTRATION);
843 }
844
James.cf Linc9f35a42020-01-15 02:35:22 +0800845 void setRcsService(TelephonyRcsService rcsService) {
846 mRcsService = rcsService;
847 }
Brad Ebinger49a72b42021-01-29 00:55:24 +0000848
849 /**
850 * Override device RCS single registration support check for CTS testing or remove override
851 * if the Boolean is set to null.
852 */
853 void setDeviceSingleRegistrationSupportOverride(Boolean deviceOverrideValue) {
854 mSingleRegistrationOverride = deviceOverrideValue;
855 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800856}