blob: 3f354547782e912884f43daf4e65696c13dfdee0 [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;
sungcheol ahn3991d2d2022-11-10 02:10:49 +000053import com.android.internal.telephony.ISipDialogStateCallback;
James.cf Lincad981c2019-12-10 20:37:56 +080054import com.android.internal.telephony.Phone;
Brad Ebinger8b79edc2020-02-27 19:13:24 -080055import com.android.internal.telephony.TelephonyPermissions;
Brad Ebingere3ae65a2020-09-11 12:45:11 -070056import com.android.internal.telephony.ims.ImsResolver;
Brad Ebingera68a4972020-01-30 17:31:23 -080057import com.android.services.telephony.rcs.RcsFeatureController;
Brad Ebingerb989c7c2020-09-23 17:03:48 -070058import com.android.services.telephony.rcs.SipTransportController;
James.cf Linc9f35a42020-01-15 02:35:22 +080059import com.android.services.telephony.rcs.TelephonyRcsService;
James.cf Lin99a360d2020-11-04 10:48:37 +080060import com.android.services.telephony.rcs.UceControllerManager;
James.cf Lincad981c2019-12-10 20:37:56 +080061
James.cf Linaf3183c2019-10-24 00:59:00 +080062import java.util.List;
Brad Ebingerd4c5bde2021-02-12 06:18:28 +000063import java.util.Set;
James.cf Linaf3183c2019-10-24 00:59:00 +080064
65/**
66 * Implementation of the IImsRcsController interface.
67 */
68public 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;
James.cf Linc9f35a42020-01-15 02:35:22 +080075 private TelephonyRcsService mRcsService;
Brad Ebingere3ae65a2020-09-11 12:45:11 -070076 private ImsResolver mImsResolver;
Brad Ebinger49a72b42021-01-29 00:55:24 +000077 // set by shell cmd phone src set-device-enabled true/false
78 private Boolean mSingleRegistrationOverride;
James.cf Linaf3183c2019-10-24 00:59:00 +080079
80 /**
Hyunho8ea90f32021-11-16 08:53:02 +000081 * 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 /**
James.cf Linaf3183c2019-10-24 00:59:00 +080090 * Initialize the singleton ImsRcsController instance.
91 * This is only done once, at startup, from PhoneApp.onCreate().
92 */
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() */
105 private ImsRcsController(PhoneGlobals app) {
106 Log.i(TAG, "ImsRcsController");
107 mApp = app;
Peter Wangc035ce42020-01-08 21:00:22 -0800108 TelephonyFrameworkInitializer
109 .getTelephonyServiceManager().getTelephonyImsServiceRegisterer().register(this);
Brad Ebingerd1947d82021-05-17 20:54:49 +0000110 mImsResolver = ImsResolver.getInstance();
James.cf Linaf3183c2019-10-24 00:59:00 +0800111 }
112
James.cf Lincad981c2019-12-10 20:37:56 +0800113 /**
Brad Ebingera68a4972020-01-30 17:31:23 -0800114 * Register a {@link RegistrationManager.RegistrationCallback} to receive IMS network
115 * registration state.
James.cf Lindc2d5422019-12-31 14:40:25 +0800116 */
117 @Override
Brad Ebingera68a4972020-01-30 17:31:23 -0800118 public void registerImsRegistrationCallback(int subId, IImsRegistrationCallback callback) {
Nathan Harold75a9ff12021-04-06 11:26:02 -0700119 TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
James.cf Linf020d162021-01-31 22:15:52 +0800120 mApp, subId, "registerImsRegistrationCallback");
James.cf Lindc2d5422019-12-31 14:40:25 +0800121 final long token = Binder.clearCallingIdentity();
122 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800123 getRcsFeatureController(subId).registerImsRegistrationCallback(subId, callback);
124 } catch (ImsException e) {
James.cf Lindc2d5422019-12-31 14:40:25 +0800125 Log.e(TAG, "registerImsRegistrationCallback: sudId=" + subId + ", " + e.getMessage());
126 throw new ServiceSpecificException(e.getCode());
127 } finally {
128 Binder.restoreCallingIdentity(token);
129 }
130 }
131
132 /**
Brad Ebingera68a4972020-01-30 17:31:23 -0800133 * Removes an existing {@link RegistrationManager.RegistrationCallback}.
James.cf Lindc2d5422019-12-31 14:40:25 +0800134 */
135 @Override
136 public void unregisterImsRegistrationCallback(int subId, IImsRegistrationCallback callback) {
Nathan Harold75a9ff12021-04-06 11:26:02 -0700137 TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
James.cf Linf020d162021-01-31 22:15:52 +0800138 mApp, subId, "unregisterImsRegistrationCallback");
James.cf Lindc2d5422019-12-31 14:40:25 +0800139 final long token = Binder.clearCallingIdentity();
140 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800141 getRcsFeatureController(subId).unregisterImsRegistrationCallback(subId, callback);
James.cf Lindc2d5422019-12-31 14:40:25 +0800142 } 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
153 public void getImsRcsRegistrationState(int subId, IIntegerConsumer consumer) {
Nathan Harold75a9ff12021-04-06 11:26:02 -0700154 TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
James.cf Linf020d162021-01-31 22:15:52 +0800155 mApp, subId, "getImsRcsRegistrationState");
James.cf Lindc2d5422019-12-31 14:40:25 +0800156 final long token = Binder.clearCallingIdentity();
157 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800158 getRcsFeatureController(subId).getRegistrationState(regState -> {
James.cf Lindc2d5422019-12-31 14:40:25 +0800159 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
175 public void getImsRcsRegistrationTransportType(int subId, IIntegerConsumer consumer) {
Nathan Harold75a9ff12021-04-06 11:26:02 -0700176 TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
James.cf Linf020d162021-01-31 22:15:52 +0800177 mApp, subId, "getImsRcsRegistrationTransportType");
James.cf Lindc2d5422019-12-31 14:40:25 +0800178 final long token = Binder.clearCallingIdentity();
179 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800180 getRcsFeatureController(subId).getRegistrationTech(regTech -> {
James.cf Lindc2d5422019-12-31 14:40:25 +0800181 // 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 /**
James.cf Lincad981c2019-12-10 20:37:56 +0800198 * 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 */
James.cf Linaf3183c2019-10-24 00:59:00 +0800204 @Override
Brad Ebingera68a4972020-01-30 17:31:23 -0800205 public void registerRcsAvailabilityCallback(int subId, IImsCapabilityCallback callback) {
James.cf Linaf3183c2019-10-24 00:59:00 +0800206 enforceReadPrivilegedPermission("registerRcsAvailabilityCallback");
James.cf Lincad981c2019-12-10 20:37:56 +0800207 final long token = Binder.clearCallingIdentity();
208 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800209 getRcsFeatureController(subId).registerRcsAvailabilityCallback(subId, callback);
210 } catch (ImsException e) {
James.cf Lincad981c2019-12-10 20:37:56 +0800211 Log.e(TAG, "registerRcsAvailabilityCallback: sudId=" + subId + ", " + e.getMessage());
212 throw new ServiceSpecificException(e.getCode());
213 } finally {
214 Binder.restoreCallingIdentity(token);
215 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800216 }
217
James.cf Lincad981c2019-12-10 20:37:56 +0800218 /**
219 * Remove the registered capability callback.
220 *
221 * @param subId the subscription ID
222 * @param callback The ImsCapabilityCallback to be removed.
223 */
James.cf Linaf3183c2019-10-24 00:59:00 +0800224 @Override
James.cf Lincad981c2019-12-10 20:37:56 +0800225 public void unregisterRcsAvailabilityCallback(int subId, IImsCapabilityCallback callback) {
James.cf Linaf3183c2019-10-24 00:59:00 +0800226 enforceReadPrivilegedPermission("unregisterRcsAvailabilityCallback");
James.cf Lincad981c2019-12-10 20:37:56 +0800227 final long token = Binder.clearCallingIdentity();
228 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800229 getRcsFeatureController(subId).unregisterRcsAvailabilityCallback(subId, callback);
Brad Ebinger919631e2021-06-02 17:46:35 -0700230 } catch (ServiceSpecificException e) {
231 Log.e(TAG, "unregisterRcsAvailabilityCallback: error=" + e.errorCode);
James.cf Lincad981c2019-12-10 20:37:56 +0800232 } finally {
233 Binder.restoreCallingIdentity(token);
234 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800235 }
236
James.cf Lincad981c2019-12-10 20:37:56 +0800237 /**
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.
James.cf Linf020d162021-01-31 22:15:52 +0800242 * @param radioTech the radio technology type that we are querying.
James.cf Lincad981c2019-12-10 20:37:56 +0800243 * @return true if the RCS capability is capable for this subscription, false otherwise.
244 */
James.cf Linaf3183c2019-10-24 00:59:00 +0800245 @Override
246 public boolean isCapable(int subId,
James.cf Lincad981c2019-12-10 20:37:56 +0800247 @RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability,
248 @ImsRegistrationImplBase.ImsRegistrationTech int radioTech) {
James.cf Linaf3183c2019-10-24 00:59:00 +0800249 enforceReadPrivilegedPermission("isCapable");
James.cf Lincad981c2019-12-10 20:37:56 +0800250 final long token = Binder.clearCallingIdentity();
251 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800252 return getRcsFeatureController(subId).isCapable(capability, radioTech);
253 } catch (ImsException e) {
James.cf Lincad981c2019-12-10 20:37:56 +0800254 Log.e(TAG, "isCapable: sudId=" + subId
255 + ", capability=" + capability + ", " + e.getMessage());
Brad Ebingere3885b22022-02-16 13:18:59 -0800256 throw new ServiceSpecificException(e.getCode(), e.getMessage());
James.cf Lincad981c2019-12-10 20:37:56 +0800257 } finally {
258 Binder.restoreCallingIdentity(token);
259 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800260 }
261
James.cf Lincad981c2019-12-10 20:37:56 +0800262 /**
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,
James.cf Linf020d162021-01-31 22:15:52 +0800268 * @param radioTech the radio technology type that we are querying.
James.cf Lincad981c2019-12-10 20:37:56 +0800269 * false otherwise.
270 */
James.cf Linaf3183c2019-10-24 00:59:00 +0800271 @Override
272 public boolean isAvailable(int subId,
James.cf Linf020d162021-01-31 22:15:52 +0800273 @RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability,
274 @ImsRegistrationImplBase.ImsRegistrationTech int radioTech) {
James.cf Linaf3183c2019-10-24 00:59:00 +0800275 enforceReadPrivilegedPermission("isAvailable");
James.cf Lincad981c2019-12-10 20:37:56 +0800276 final long token = Binder.clearCallingIdentity();
277 try {
James.cf Linf020d162021-01-31 22:15:52 +0800278 return getRcsFeatureController(subId).isAvailable(capability, radioTech);
Brad Ebingera68a4972020-01-30 17:31:23 -0800279 } catch (ImsException e) {
James.cf Lincad981c2019-12-10 20:37:56 +0800280 Log.e(TAG, "isAvailable: sudId=" + subId
281 + ", capability=" + capability + ", " + e.getMessage());
Brad Ebingere3885b22022-02-16 13:18:59 -0800282 throw new ServiceSpecificException(e.getCode(), e.getMessage());
James.cf Lincad981c2019-12-10 20:37:56 +0800283 } finally {
284 Binder.restoreCallingIdentity(token);
285 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800286 }
287
288 @Override
Brad Ebinger8b79edc2020-02-27 19:13:24 -0800289 public void requestCapabilities(int subId, String callingPackage, String callingFeatureId,
290 List<Uri> contactNumbers, IRcsUceControllerCallback c) {
James.cf Lin051dd252021-01-21 03:30:54 +0800291 enforceAccessUserCapabilityExchangePermission("requestCapabilities");
292 enforceReadContactsPermission("requestCapabilities");
Brad Ebingera68a4972020-01-30 17:31:23 -0800293 final long token = Binder.clearCallingIdentity();
294 try {
James.cf Lin99a360d2020-11-04 10:48:37 +0800295 UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
296 UceControllerManager.class);
297 if (uceCtrlManager == null) {
Brad Ebingera68a4972020-01-30 17:31:23 -0800298 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
299 "This subscription does not support UCE.");
300 }
James.cf Lin99a360d2020-11-04 10:48:37 +0800301 uceCtrlManager.requestCapabilities(contactNumbers, c);
302 } catch (ImsException e) {
303 throw new ServiceSpecificException(e.getCode(), e.getMessage());
Brad Ebingera68a4972020-01-30 17:31:23 -0800304 } finally {
305 Binder.restoreCallingIdentity(token);
Brad Ebinger1aa94992020-01-22 14:17:23 -0800306 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800307 }
308
309 @Override
James.cf Linbcdf8b32021-01-14 16:44:13 +0800310 public void requestAvailability(int subId, String callingPackage,
James.cf Lin64e91212020-10-30 01:09:52 +0800311 String callingFeatureId, Uri contactNumber, IRcsUceControllerCallback c) {
James.cf Lin051dd252021-01-21 03:30:54 +0800312 enforceAccessUserCapabilityExchangePermission("requestAvailability");
313 enforceReadContactsPermission("requestAvailability");
Brad Ebingera68a4972020-01-30 17:31:23 -0800314 final long token = Binder.clearCallingIdentity();
315 try {
James.cf Lin99a360d2020-11-04 10:48:37 +0800316 UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
317 UceControllerManager.class);
318 if (uceCtrlManager == null) {
Brad Ebingera68a4972020-01-30 17:31:23 -0800319 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
320 "This subscription does not support UCE.");
321 }
James.cf Lin99a360d2020-11-04 10:48:37 +0800322 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
331 public @PublishState int getUcePublishState(int subId) {
332 enforceReadPrivilegedPermission("getUcePublishState");
Hyunho8ea90f32021-11-16 08:53:02 +0000333 final int uid = Binder.getCallingUid();
James.cf Lin99a360d2020-11-04 10:48:37 +0800334 final long token = Binder.clearCallingIdentity();
Hyunho8ea90f32021-11-16 08:53:02 +0000335 boolean isSupportPublishingState = false;
James.cf Lin99a360d2020-11-04 10:48:37 +0800336 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 }
Hyunho8ea90f32021-11-16 08:53:02 +0000343 if (CompatChanges.isChangeEnabled(SUPPORT_PUBLISHING_STATE, uid)) {
344 isSupportPublishingState = true;
345 }
346 return uceCtrlManager.getUcePublishState(isSupportPublishingState);
James.cf Lin99a360d2020-11-04 10:48:37 +0800347 } catch (ImsException e) {
348 throw new ServiceSpecificException(e.getCode(), e.getMessage());
349 } finally {
350 Binder.restoreCallingIdentity(token);
351 }
352 }
353
Brad Ebingerd4c5bde2021-02-12 06:18:28 +0000354 /**
355 * Add new feature tags to the Set used to calculate the capabilities in PUBLISH.
356 */
357 // Used for SHELL command only right now.
358 public RcsContactUceCapability addUceRegistrationOverrideShell(int subId,
359 Set<String> featureTags) throws ImsException {
360 // Permission check happening in PhoneInterfaceManager.
Brad Ebinger919631e2021-06-02 17:46:35 -0700361 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);
Brad Ebingerd4c5bde2021-02-12 06:18:28 +0000370 }
Brad Ebingerd4c5bde2021-02-12 06:18:28 +0000371 }
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.
377 public RcsContactUceCapability removeUceRegistrationOverrideShell(int subId,
378 Set<String> featureTags) throws ImsException {
379 // Permission check happening in PhoneInterfaceManager.
Brad Ebinger919631e2021-06-02 17:46:35 -0700380 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);
Brad Ebingerd4c5bde2021-02-12 06:18:28 +0000389 }
Brad Ebingerd4c5bde2021-02-12 06:18:28 +0000390 }
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.
396 public RcsContactUceCapability clearUceRegistrationOverrideShell(int subId)
397 throws ImsException {
Brad Ebinger919631e2021-06-02 17:46:35 -0700398 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);
Brad Ebingerd4c5bde2021-02-12 06:18:28 +0000408 }
Brad Ebingerd4c5bde2021-02-12 06:18:28 +0000409 }
410
411 /**
412 * @return current RcsContactUceCapability instance that will be used for PUBLISH.
413 */
414 // Used for SHELL command only right now.
415 public RcsContactUceCapability getLatestRcsContactUceCapabilityShell(int subId)
416 throws ImsException {
Brad Ebinger919631e2021-06-02 17:46:35 -0700417 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);
Brad Ebingerd4c5bde2021-02-12 06:18:28 +0000427 }
Brad Ebingerd4c5bde2021-02-12 06:18:28 +0000428 }
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.
435 public String getLastUcePidfXmlShell(int subId) throws ImsException {
Brad Ebinger919631e2021-06-02 17:46:35 -0700436 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);
Brad Ebingerd4c5bde2021-02-12 06:18:28 +0000447 }
Brad Ebingerd4c5bde2021-02-12 06:18:28 +0000448 }
449
James.cf Line8713a42021-04-29 16:04:26 +0800450 /**
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.
455 public boolean removeUceRequestDisallowedStatus(int subId) throws ImsException {
Brad Ebinger919631e2021-06-02 17:46:35 -0700456 try {
James.cf Linc6b449f2021-06-05 01:11:15 +0800457 UceControllerManager uceCtrlManager = getRcsFeatureController(subId, true).getFeature(
Brad Ebinger919631e2021-06-02 17:46:35 -0700458 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);
James.cf Line8713a42021-04-29 16:04:26 +0800465 }
James.cf Line8713a42021-04-29 16:04:26 +0800466 }
467
James.cf Lin0fc71b02021-05-25 01:37:38 +0800468 /**
469 * Set the timeout for contact capabilities request.
470 */
471 // Used for SHELL command only right now.
472 public boolean setCapabilitiesRequestTimeout(int subId, long timeoutAfter) throws ImsException {
Brad Ebinger919631e2021-06-02 17:46:35 -0700473 try {
James.cf Linc6b449f2021-06-05 01:11:15 +0800474 UceControllerManager uceCtrlManager = getRcsFeatureController(subId, true).getFeature(
Brad Ebinger919631e2021-06-02 17:46:35 -0700475 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);
James.cf Lin0fc71b02021-05-25 01:37:38 +0800482 }
James.cf Lin0fc71b02021-05-25 01:37:38 +0800483 }
484
James.cf Lin99a360d2020-11-04 10:48:37 +0800485 @Override
486 public void registerUcePublishStateCallback(int subId, IRcsUcePublishStateCallback c) {
487 enforceReadPrivilegedPermission("registerUcePublishStateCallback");
Hyunho8ea90f32021-11-16 08:53:02 +0000488 final int uid = Binder.getCallingUid();
James.cf Lin99a360d2020-11-04 10:48:37 +0800489 final long token = Binder.clearCallingIdentity();
Hyunho8ea90f32021-11-16 08:53:02 +0000490 boolean isSupportPublishingState = false;
James.cf Lin99a360d2020-11-04 10:48:37 +0800491 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 }
Hyunho8ea90f32021-11-16 08:53:02 +0000498
499 if (CompatChanges.isChangeEnabled(SUPPORT_PUBLISHING_STATE, uid)) {
500 isSupportPublishingState = true;
501 }
502 uceCtrlManager.registerPublishStateCallback(c, isSupportPublishingState);
James.cf Lin99a360d2020-11-04 10:48:37 +0800503 } catch (ImsException e) {
504 throw new ServiceSpecificException(e.getCode(), e.getMessage());
505 } finally {
506 Binder.restoreCallingIdentity(token);
507 }
508 }
509
510 @Override
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);
Brad Ebinger919631e2021-06-02 17:46:35 -0700522 } catch (ServiceSpecificException e) {
523 Log.e(TAG, "unregisterUcePublishStateCallback: error=" + e.errorCode);
Brad Ebingera68a4972020-01-30 17:31:23 -0800524 } finally {
525 Binder.restoreCallingIdentity(token);
Brad Ebinger1aa94992020-01-22 14:17:23 -0800526 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800527 }
528
529 @Override
Brad Ebinger8b79edc2020-02-27 19:13:24 -0800530 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 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800544 }
545
546 @Override
547 public void setUceSettingEnabled(int subId, boolean isEnabled) {
548 enforceModifyPermission();
Brad Ebinger8b79edc2020-02-27 19:13:24 -0800549 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 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800556 }
557
Brad Ebingerb989c7c2020-09-23 17:03:48 -0700558 @Override
559 public boolean isSipDelegateSupported(int subId) {
Brad Ebinger4df7e242021-02-17 23:23:21 +0000560 TelephonyPermissions.enforceAnyPermissionGranted(mApp, Binder.getCallingUid(),
561 "isSipDelegateSupported",
562 Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION,
563 Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
Brad Ebinger49a72b42021-01-29 00:55:24 +0000564 if (!isImsSingleRegistrationSupportedOnDevice()) {
565 return false;
566 }
Brad Ebingerb989c7c2020-09-23 17:03:48 -0700567 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
Brad Ebingeraf1e9832020-10-14 10:49:28 -0700587 @Override
Brad Ebinger63b6f5a2020-10-27 11:43:35 -0700588 public void createSipDelegate(int subId, DelegateRequest request, String packageName,
Brad Ebingeraf1e9832020-10-14 10:49:28 -0700589 ISipDelegateConnectionStateCallback delegateState,
590 ISipDelegateMessageCallback delegateMessage) {
Brad Ebinger4df7e242021-02-17 23:23:21 +0000591 enforceImsSingleRegistrationPermission("createSipDelegate");
Brad Ebinger49a72b42021-01-29 00:55:24 +0000592 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 }
Brad Ebinger63b6f5a2020-10-27 11:43:35 -0700597 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 }
Brad Ebingeraf1e9832020-10-14 10:49:28 -0700609
Jinyoung Jeongca77e1c2021-10-21 04:34:46 +0000610 final int uid = Binder.getCallingUid();
Brad Ebingeraf1e9832020-10-14 10:49:28 -0700611 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 {
Jinyoung Jeongca77e1c2021-10-21 04:34:46 +0000619 transport.createSipDelegate(subId, uid, request, packageName, delegateState,
Brad Ebinger63b6f5a2020-10-27 11:43:35 -0700620 delegateMessage);
Brad Ebingeraf1e9832020-10-14 10:49:28 -0700621 } catch (ImsException e) {
622 throw new ServiceSpecificException(e.getCode(), e.getMessage());
623 } finally {
624 Binder.restoreCallingIdentity(identity);
625 }
626 }
627
628 @Override
629 public void destroySipDelegate(int subId, ISipDelegate connection, int reason) {
Brad Ebinger652411e2021-06-30 09:30:35 -0700630 // 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 }
Brad Ebingeraf1e9832020-10-14 10:49:28 -0700635 final long identity = Binder.clearCallingIdentity();
636 try {
Brad Ebinger63b6f5a2020-10-27 11:43:35 -0700637 SipTransportController transport = getRcsFeatureController(subId).getFeature(
638 SipTransportController.class);
639 if (transport == null) {
640 return;
641 }
642 transport.destroySipDelegate(subId, connection, reason);
Brad Ebinger919631e2021-06-02 17:46:35 -0700643 } catch (ServiceSpecificException e) {
644 Log.e(TAG, "destroySipDelegate: error=" + e.errorCode);
Brad Ebingeraf1e9832020-10-14 10:49:28 -0700645 } finally {
646 Binder.restoreCallingIdentity(identity);
647 }
648 }
649
Brad Ebinger36221382020-12-09 00:33:39 +0000650 @Override
651 public void triggerNetworkRegistration(int subId, ISipDelegate connection, int sipCode,
652 String sipReason) {
Brad Ebinger4df7e242021-02-17 23:23:21 +0000653 enforceImsSingleRegistrationPermission("triggerNetworkRegistration");
Brad Ebinger36221382020-12-09 00:33:39 +0000654
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);
Brad Ebinger919631e2021-06-02 17:46:35 -0700663 } catch (ServiceSpecificException e) {
664 Log.e(TAG, "triggerNetworkRegistration: error=" + e.errorCode);
Brad Ebinger36221382020-12-09 00:33:39 +0000665 } finally {
666 Binder.restoreCallingIdentity(identity);
667 }
668 }
669
James.cf Linaf3183c2019-10-24 00:59:00 +0800670 /**
sungcheol ahn3991d2d2022-11-10 02:10:49 +0000671 * Register a state of Sip Dialog callback
672 */
673 @Override
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
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 /**
Brad Ebingere3ae65a2020-09-11 12:45:11 -0700725 * Registers for updates to the RcsFeature connection through the IImsServiceFeatureCallback
726 * callback.
727 */
728 @Override
Brad Ebinger6366ce92020-10-01 13:51:05 -0700729 public void registerRcsFeatureCallback(int slotId, IImsServiceFeatureCallback callback) {
Brad Ebingere3ae65a2020-09-11 12:45:11 -0700730 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 }
Brad Ebinger6366ce92020-10-01 13:51:05 -0700738 mImsResolver.listenForFeature(slotId, ImsFeature.FEATURE_RCS, callback);
Brad Ebingere3ae65a2020-09-11 12:45:11 -0700739 } finally {
740 Binder.restoreCallingIdentity(identity);
741 }
742 }
Brad Ebinger6366ce92020-10-01 13:51:05 -0700743
Brad Ebingere3ae65a2020-09-11 12:45:11 -0700744 /**
745 * Unregister a previously registered IImsServiceFeatureCallback associated with an ImsFeature.
746 */
747 @Override
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 /**
James.cf Linaf3183c2019-10-24 00:59:00 +0800761 * 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 */
765 private void enforceReadPrivilegedPermission(String message) {
766 mApp.enforceCallingOrSelfPermission(
767 android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, message);
768 }
769
770 /**
Brad Ebinger4df7e242021-02-17 23:23:21 +0000771 * @throws SecurityException if the caller does not have the required
772 * PERFORM_IMS_SINGLE_REGISTRATION permission.
773 */
774 private void enforceImsSingleRegistrationPermission(String message) {
775 mApp.enforceCallingOrSelfPermission(
776 Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION, message);
777 }
778
779 /**
James.cf Linaf3183c2019-10-24 00:59:00 +0800780 * Make sure the caller has the MODIFY_PHONE_STATE permission.
781 *
782 * @throws SecurityException if the caller does not have the required permission
783 */
784 private void enforceModifyPermission() {
785 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE, null);
786 }
James.cf Lincad981c2019-12-10 20:37:56 +0800787
788 /**
James.cf Lin051dd252021-01-21 03:30:54 +0800789 * 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 */
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 */
803 private void enforceReadContactsPermission(String message) {
804 mApp.enforceCallingOrSelfPermission(
805 android.Manifest.permission.READ_CONTACTS, message);
806 }
807
808 /**
James.cf Lindc2d5422019-12-31 14:40:25 +0800809 * Retrieve RcsFeatureManager instance.
810 *
811 * @param subId the subscription ID
812 * @return The RcsFeatureManager instance
813 * @throws ServiceSpecificException if getting RcsFeatureManager instance failed.
814 */
Brad Ebingera68a4972020-01-30 17:31:23 -0800815 private RcsFeatureController getRcsFeatureController(int subId) {
James.cf Linc6b449f2021-06-05 01:11:15 +0800816 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 */
827 private RcsFeatureController getRcsFeatureController(int subId, boolean skipVerifyingConfig) {
James.cf Lindc2d5422019-12-31 14:40:25 +0800828 if (!ImsManager.isImsSupportedOnDevice(mApp)) {
James.cf Lincad981c2019-12-10 20:37:56 +0800829 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
James.cf Lindc2d5422019-12-31 14:40:25 +0800830 "IMS is not available on device.");
831 }
Brad Ebingera68a4972020-01-30 17:31:23 -0800832 if (mRcsService == null) {
833 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
834 "IMS is not available on device.");
835 }
James.cf Lindc2d5422019-12-31 14:40:25 +0800836 Phone phone = PhoneGlobals.getPhone(subId);
837 if (phone == null) {
838 throw new ServiceSpecificException(ImsException.CODE_ERROR_INVALID_SUBSCRIPTION,
839 "Invalid subscription Id: " + subId);
840 }
Brad Ebingera68a4972020-01-30 17:31:23 -0800841 int slotId = phone.getPhoneId();
James.cf Linc6b449f2021-06-05 01:11:15 +0800842 if (!skipVerifyingConfig) {
843 verifyImsRcsConfiguredOrThrow(slotId);
Brad Ebingere3885b22022-02-16 13:18:59 -0800844 verifyRcsSubIdActiveOrThrow(slotId, subId);
James.cf Linc6b449f2021-06-05 01:11:15 +0800845 }
Brad Ebingera68a4972020-01-30 17:31:23 -0800846 RcsFeatureController c = mRcsService.getFeatureController(slotId);
847 if (c == null) {
Brad Ebingere3885b22022-02-16 13:18:59 -0800848 // 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.
Brad Ebinger036dc9e2020-02-06 15:49:06 -0800851 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
852 "The requested operation is not supported for subId " + subId);
James.cf Lincad981c2019-12-10 20:37:56 +0800853 }
Brad Ebingere3885b22022-02-16 13:18:59 -0800854 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 }
Brad Ebingera68a4972020-01-30 17:31:23 -0800863 return c;
James.cf Lincad981c2019-12-10 20:37:56 +0800864 }
James.cf Linc9f35a42020-01-15 02:35:22 +0800865
Brad Ebinger919631e2021-06-02 17:46:35 -0700866 /**
Brad Ebingere3885b22022-02-16 13:18:59 -0800867 * Ensure the TelephonyRcsService is tracking the supplied subId for the supplied slotId and has
868 * set up the stack.
869 */
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 /**
Brad Ebinger919631e2021-06-02 17:46:35 -0700881 * 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 */
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
Brad Ebinger49a72b42021-01-29 00:55:24 +0000894 private boolean isImsSingleRegistrationSupportedOnDevice() {
895 return mSingleRegistrationOverride != null ? mSingleRegistrationOverride
896 : mApp.getPackageManager().hasSystemFeature(
897 PackageManager.FEATURE_TELEPHONY_IMS_SINGLE_REGISTRATION);
898 }
899
James.cf Linc9f35a42020-01-15 02:35:22 +0800900 void setRcsService(TelephonyRcsService rcsService) {
901 mRcsService = rcsService;
902 }
Brad Ebinger49a72b42021-01-29 00:55:24 +0000903
904 /**
905 * Override device RCS single registration support check for CTS testing or remove override
906 * if the Boolean is set to null.
907 */
908 void setDeviceSingleRegistrationSupportOverride(Boolean deviceOverrideValue) {
909 mSingleRegistrationOverride = deviceOverrideValue;
910 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800911}