blob: 1d33514dca6d5b247be36df7ca26c77e1abac4ac [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
James.cf Linaf3183c2019-10-24 00:59:00 +080019import android.net.Uri;
James.cf Lincad981c2019-12-10 20:37:56 +080020import android.os.Binder;
21import android.os.RemoteException;
James.cf Lincad981c2019-12-10 20:37:56 +080022import android.os.ServiceSpecificException;
Brad Ebingerb7a866a2020-01-22 17:51:55 -080023import android.telephony.SubscriptionManager;
Peter Wangc035ce42020-01-08 21:00:22 -080024import android.telephony.TelephonyFrameworkInitializer;
James.cf Lincad981c2019-12-10 20:37:56 +080025import android.telephony.ims.ImsException;
James.cf Lindc2d5422019-12-31 14:40:25 +080026import android.telephony.ims.RegistrationManager;
James.cf Linaf3183c2019-10-24 00:59:00 +080027import android.telephony.ims.aidl.IImsCapabilityCallback;
28import android.telephony.ims.aidl.IImsRcsController;
James.cf Lindc2d5422019-12-31 14:40:25 +080029import android.telephony.ims.aidl.IImsRegistrationCallback;
James.cf Linaf3183c2019-10-24 00:59:00 +080030import android.telephony.ims.aidl.IRcsUceControllerCallback;
James.cf Lincdad3862020-02-25 15:55:03 +080031import android.telephony.ims.aidl.IRcsUcePublishStateCallback;
Brad Ebingere3ae65a2020-09-11 12:45:11 -070032import android.telephony.ims.feature.ImsFeature;
James.cf Linaf3183c2019-10-24 00:59:00 +080033import android.telephony.ims.feature.RcsFeature;
James.cf Lincad981c2019-12-10 20:37:56 +080034import android.telephony.ims.stub.ImsRegistrationImplBase;
James.cf Linaf3183c2019-10-24 00:59:00 +080035import android.util.Log;
36
James.cf Lindc2d5422019-12-31 14:40:25 +080037import com.android.ims.ImsManager;
Brad Ebingere3ae65a2020-09-11 12:45:11 -070038import com.android.ims.internal.IImsServiceFeatureCallback;
James.cf Lindc2d5422019-12-31 14:40:25 +080039import com.android.internal.telephony.IIntegerConsumer;
James.cf Lincad981c2019-12-10 20:37:56 +080040import com.android.internal.telephony.Phone;
Brad Ebinger8b79edc2020-02-27 19:13:24 -080041import com.android.internal.telephony.TelephonyPermissions;
Brad Ebingere3ae65a2020-09-11 12:45:11 -070042import com.android.internal.telephony.ims.ImsResolver;
James.cf Lincad981c2019-12-10 20:37:56 +080043import com.android.internal.telephony.imsphone.ImsPhone;
Brad Ebingera68a4972020-01-30 17:31:23 -080044import com.android.services.telephony.rcs.RcsFeatureController;
James.cf Linc9f35a42020-01-15 02:35:22 +080045import com.android.services.telephony.rcs.TelephonyRcsService;
Brad Ebingera68a4972020-01-30 17:31:23 -080046import com.android.services.telephony.rcs.UserCapabilityExchangeImpl;
James.cf Lincad981c2019-12-10 20:37:56 +080047
James.cf Linaf3183c2019-10-24 00:59:00 +080048import java.util.List;
49
50/**
51 * Implementation of the IImsRcsController interface.
52 */
53public class ImsRcsController extends IImsRcsController.Stub {
54 private static final String TAG = "ImsRcsController";
55
56 /** The singleton instance. */
57 private static ImsRcsController sInstance;
58
59 private PhoneGlobals mApp;
James.cf Linc9f35a42020-01-15 02:35:22 +080060 private TelephonyRcsService mRcsService;
Brad Ebingere3ae65a2020-09-11 12:45:11 -070061 private ImsResolver mImsResolver;
James.cf Linaf3183c2019-10-24 00:59:00 +080062
63 /**
64 * Initialize the singleton ImsRcsController instance.
65 * This is only done once, at startup, from PhoneApp.onCreate().
66 */
67 static ImsRcsController init(PhoneGlobals app) {
68 synchronized (ImsRcsController.class) {
69 if (sInstance == null) {
70 sInstance = new ImsRcsController(app);
71 } else {
72 Log.wtf(TAG, "init() called multiple times! sInstance = " + sInstance);
73 }
74 return sInstance;
75 }
76 }
77
78 /** Private constructor; @see init() */
79 private ImsRcsController(PhoneGlobals app) {
80 Log.i(TAG, "ImsRcsController");
81 mApp = app;
Peter Wangc035ce42020-01-08 21:00:22 -080082 TelephonyFrameworkInitializer
83 .getTelephonyServiceManager().getTelephonyImsServiceRegisterer().register(this);
Brad Ebingere3ae65a2020-09-11 12:45:11 -070084 mImsResolver = mApp.getImsResolver();
James.cf Linaf3183c2019-10-24 00:59:00 +080085 }
86
James.cf Lincad981c2019-12-10 20:37:56 +080087 /**
Brad Ebingera68a4972020-01-30 17:31:23 -080088 * Register a {@link RegistrationManager.RegistrationCallback} to receive IMS network
89 * registration state.
James.cf Lindc2d5422019-12-31 14:40:25 +080090 */
91 @Override
Brad Ebingera68a4972020-01-30 17:31:23 -080092 public void registerImsRegistrationCallback(int subId, IImsRegistrationCallback callback) {
James.cf Lindc2d5422019-12-31 14:40:25 +080093 enforceReadPrivilegedPermission("registerImsRegistrationCallback");
94 final long token = Binder.clearCallingIdentity();
95 try {
Brad Ebingera68a4972020-01-30 17:31:23 -080096 getRcsFeatureController(subId).registerImsRegistrationCallback(subId, callback);
97 } catch (ImsException e) {
James.cf Lindc2d5422019-12-31 14:40:25 +080098 Log.e(TAG, "registerImsRegistrationCallback: sudId=" + subId + ", " + e.getMessage());
99 throw new ServiceSpecificException(e.getCode());
100 } finally {
101 Binder.restoreCallingIdentity(token);
102 }
103 }
104
105 /**
Brad Ebingera68a4972020-01-30 17:31:23 -0800106 * Removes an existing {@link RegistrationManager.RegistrationCallback}.
James.cf Lindc2d5422019-12-31 14:40:25 +0800107 */
108 @Override
109 public void unregisterImsRegistrationCallback(int subId, IImsRegistrationCallback callback) {
110 enforceReadPrivilegedPermission("unregisterImsRegistrationCallback");
111 final long token = Binder.clearCallingIdentity();
112 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800113 getRcsFeatureController(subId).unregisterImsRegistrationCallback(subId, callback);
James.cf Lindc2d5422019-12-31 14:40:25 +0800114 } catch (ServiceSpecificException e) {
115 Log.e(TAG, "unregisterImsRegistrationCallback: error=" + e.errorCode);
116 } finally {
117 Binder.restoreCallingIdentity(token);
118 }
119 }
120
121 /**
122 * Get the IMS service registration state for the RcsFeature associated with this sub id.
123 */
124 @Override
125 public void getImsRcsRegistrationState(int subId, IIntegerConsumer consumer) {
126 enforceReadPrivilegedPermission("getImsRcsRegistrationState");
127 final long token = Binder.clearCallingIdentity();
128 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800129 getRcsFeatureController(subId).getRegistrationState(regState -> {
James.cf Lindc2d5422019-12-31 14:40:25 +0800130 try {
131 consumer.accept((regState == null)
132 ? RegistrationManager.REGISTRATION_STATE_NOT_REGISTERED : regState);
133 } catch (RemoteException e) {
134 Log.w(TAG, "getImsRcsRegistrationState: callback is not available.");
135 }
136 });
137 } finally {
138 Binder.restoreCallingIdentity(token);
139 }
140 }
141
142 /**
143 * Gets the Transport Type associated with the current IMS RCS registration.
144 */
145 @Override
146 public void getImsRcsRegistrationTransportType(int subId, IIntegerConsumer consumer) {
147 enforceReadPrivilegedPermission("getImsRcsRegistrationTransportType");
148 final long token = Binder.clearCallingIdentity();
149 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800150 getRcsFeatureController(subId).getRegistrationTech(regTech -> {
James.cf Lindc2d5422019-12-31 14:40:25 +0800151 // Convert registration tech from ImsRegistrationImplBase -> RegistrationManager
152 int regTechConverted = (regTech == null)
153 ? ImsRegistrationImplBase.REGISTRATION_TECH_NONE : regTech;
154 regTechConverted = RegistrationManager.IMS_REG_TO_ACCESS_TYPE_MAP.get(
155 regTechConverted);
156 try {
157 consumer.accept(regTechConverted);
158 } catch (RemoteException e) {
159 Log.w(TAG, "getImsRcsRegistrationTransportType: callback is not available.");
160 }
161 });
162 } finally {
163 Binder.restoreCallingIdentity(token);
164 }
165 }
166
167 /**
James.cf Lincad981c2019-12-10 20:37:56 +0800168 * Register a capability callback which will provide RCS availability updates for the
169 * subscription specified.
170 *
171 * @param subId the subscription ID
172 * @param callback The ImsCapabilityCallback to be registered.
173 */
James.cf Linaf3183c2019-10-24 00:59:00 +0800174 @Override
Brad Ebingera68a4972020-01-30 17:31:23 -0800175 public void registerRcsAvailabilityCallback(int subId, IImsCapabilityCallback callback) {
James.cf Linaf3183c2019-10-24 00:59:00 +0800176 enforceReadPrivilegedPermission("registerRcsAvailabilityCallback");
James.cf Lincad981c2019-12-10 20:37:56 +0800177 final long token = Binder.clearCallingIdentity();
178 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800179 getRcsFeatureController(subId).registerRcsAvailabilityCallback(subId, callback);
180 } catch (ImsException e) {
James.cf Lincad981c2019-12-10 20:37:56 +0800181 Log.e(TAG, "registerRcsAvailabilityCallback: sudId=" + subId + ", " + e.getMessage());
182 throw new ServiceSpecificException(e.getCode());
183 } finally {
184 Binder.restoreCallingIdentity(token);
185 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800186 }
187
James.cf Lincad981c2019-12-10 20:37:56 +0800188 /**
189 * Remove the registered capability callback.
190 *
191 * @param subId the subscription ID
192 * @param callback The ImsCapabilityCallback to be removed.
193 */
James.cf Linaf3183c2019-10-24 00:59:00 +0800194 @Override
James.cf Lincad981c2019-12-10 20:37:56 +0800195 public void unregisterRcsAvailabilityCallback(int subId, IImsCapabilityCallback callback) {
James.cf Linaf3183c2019-10-24 00:59:00 +0800196 enforceReadPrivilegedPermission("unregisterRcsAvailabilityCallback");
James.cf Lincad981c2019-12-10 20:37:56 +0800197 final long token = Binder.clearCallingIdentity();
198 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800199 getRcsFeatureController(subId).unregisterRcsAvailabilityCallback(subId, callback);
James.cf Lincad981c2019-12-10 20:37:56 +0800200 } finally {
201 Binder.restoreCallingIdentity(token);
202 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800203 }
204
James.cf Lincdad3862020-02-25 15:55:03 +0800205 @Override
206 public void registerUcePublishStateCallback(int subId, IRcsUcePublishStateCallback c) {
207 enforceReadPrivilegedPermission("registerUcePublishStateCallback");
208 final long token = Binder.clearCallingIdentity();
209 try {
210 UserCapabilityExchangeImpl uce = getRcsFeatureController(subId).getFeature(
211 UserCapabilityExchangeImpl.class);
212 if (uce == null) {
213 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
214 "This subscription does not support UCE.");
215 }
216 uce.registerPublishStateCallback(c);
217 } finally {
218 Binder.restoreCallingIdentity(token);
219 }
220 }
221
222 @Override
223 public void unregisterUcePublishStateCallback(int subId, IRcsUcePublishStateCallback c) {
224 enforceReadPrivilegedPermission("unregisterUcePublishStateCallback");
225 final long token = Binder.clearCallingIdentity();
226 try {
227 UserCapabilityExchangeImpl uce = getRcsFeatureController(subId).getFeature(
228 UserCapabilityExchangeImpl.class);
229 if (uce == null) {
230 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
231 "This subscription does not support UCE.");
232 }
233 uce.unregisterUcePublishStateCallback(c);
234 } finally {
235 Binder.restoreCallingIdentity(token);
236 }
237 }
238
James.cf Lincad981c2019-12-10 20:37:56 +0800239 /**
240 * Query for the capability of an IMS RCS service
241 *
242 * @param subId the subscription ID
243 * @param capability the RCS capability to query.
244 * @param radioTech the radio tech that this capability failed for
245 * @return true if the RCS capability is capable for this subscription, false otherwise.
246 */
James.cf Linaf3183c2019-10-24 00:59:00 +0800247 @Override
248 public boolean isCapable(int subId,
James.cf Lincad981c2019-12-10 20:37:56 +0800249 @RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability,
250 @ImsRegistrationImplBase.ImsRegistrationTech int radioTech) {
James.cf Linaf3183c2019-10-24 00:59:00 +0800251 enforceReadPrivilegedPermission("isCapable");
James.cf Lincad981c2019-12-10 20:37:56 +0800252 final long token = Binder.clearCallingIdentity();
253 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800254 return getRcsFeatureController(subId).isCapable(capability, radioTech);
255 } catch (ImsException e) {
James.cf Lincad981c2019-12-10 20:37:56 +0800256 Log.e(TAG, "isCapable: sudId=" + subId
257 + ", capability=" + capability + ", " + e.getMessage());
258 return false;
259 } finally {
260 Binder.restoreCallingIdentity(token);
261 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800262 }
263
James.cf Lincad981c2019-12-10 20:37:56 +0800264 /**
265 * Query the availability of an IMS RCS capability.
266 *
267 * @param subId the subscription ID
268 * @param capability the RCS capability to query.
269 * @return true if the RCS capability is currently available for the associated subscription,
270 * false otherwise.
271 */
James.cf Linaf3183c2019-10-24 00:59:00 +0800272 @Override
273 public boolean isAvailable(int subId,
274 @RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability) {
275 enforceReadPrivilegedPermission("isAvailable");
James.cf Lincad981c2019-12-10 20:37:56 +0800276 final long token = Binder.clearCallingIdentity();
277 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800278 return getRcsFeatureController(subId).isAvailable(capability);
279 } catch (ImsException e) {
James.cf Lincad981c2019-12-10 20:37:56 +0800280 Log.e(TAG, "isAvailable: sudId=" + subId
281 + ", capability=" + capability + ", " + e.getMessage());
282 return false;
283 } 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 Linaf3183c2019-10-24 00:59:00 +0800291 enforceReadPrivilegedPermission("requestCapabilities");
Brad Ebinger8b79edc2020-02-27 19:13:24 -0800292 if (!isUceSettingEnabled(subId, callingPackage, callingFeatureId)) {
293 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
294 "The user has not enabled UCE for this subscription.");
295 }
Brad Ebingera68a4972020-01-30 17:31:23 -0800296 final long token = Binder.clearCallingIdentity();
297 try {
298 UserCapabilityExchangeImpl uce = getRcsFeatureController(subId).getFeature(
299 UserCapabilityExchangeImpl.class);
300 if (uce == null) {
301 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
302 "This subscription does not support UCE.");
303 }
304 uce.requestCapabilities(contactNumbers, c);
305 } finally {
306 Binder.restoreCallingIdentity(token);
Brad Ebinger1aa94992020-01-22 14:17:23 -0800307 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800308 }
309
310 @Override
311 public int getUcePublishState(int subId) {
312 enforceReadPrivilegedPermission("getUcePublishState");
Brad Ebingera68a4972020-01-30 17:31:23 -0800313 final long token = Binder.clearCallingIdentity();
314 try {
315 UserCapabilityExchangeImpl uce = getRcsFeatureController(subId).getFeature(
316 UserCapabilityExchangeImpl.class);
317 if (uce == null) {
318 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
319 "This subscription does not support UCE.");
320 }
321 return uce.getUcePublishState();
322 } finally {
323 Binder.restoreCallingIdentity(token);
Brad Ebinger1aa94992020-01-22 14:17:23 -0800324 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800325 }
326
327 @Override
Brad Ebinger8b79edc2020-02-27 19:13:24 -0800328 public boolean isUceSettingEnabled(int subId, String callingPackage, String callingFeatureId) {
329 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
330 mApp, subId, callingPackage, callingFeatureId, "isUceSettingEnabled")) {
331 Log.w(TAG, "isUceSettingEnabled: READ_PHONE_STATE app op disabled when accessing "
332 + "isUceSettingEnabled");
333 return false;
334 }
335 final long token = Binder.clearCallingIdentity();
336 try {
337 return SubscriptionManager.getBooleanSubscriptionProperty(subId,
338 SubscriptionManager.IMS_RCS_UCE_ENABLED, false /*defaultValue*/, mApp);
339 } finally {
340 Binder.restoreCallingIdentity(token);
341 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800342 }
343
344 @Override
345 public void setUceSettingEnabled(int subId, boolean isEnabled) {
346 enforceModifyPermission();
Brad Ebinger8b79edc2020-02-27 19:13:24 -0800347 final long token = Binder.clearCallingIdentity();
348 try {
349 SubscriptionManager.setSubscriptionProperty(subId,
350 SubscriptionManager.IMS_RCS_UCE_ENABLED, (isEnabled ? "1" : "0"));
351 } finally {
352 Binder.restoreCallingIdentity(token);
353 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800354 }
355
356 /**
Brad Ebingere3ae65a2020-09-11 12:45:11 -0700357 * Registers for updates to the RcsFeature connection through the IImsServiceFeatureCallback
358 * callback.
359 */
360 @Override
361 public void registerRcsFeatureCallback(int slotId, IImsServiceFeatureCallback callback,
362 boolean oneShot) {
363 enforceModifyPermission();
364
365 final long identity = Binder.clearCallingIdentity();
366 try {
367 if (mImsResolver == null) {
368 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
369 "Device does not support IMS");
370 }
371 if (oneShot) {
372 mImsResolver.callBackIfExists(slotId, ImsFeature.FEATURE_RCS, callback);
373 } else {
374 mImsResolver.listenForFeature(slotId, ImsFeature.FEATURE_RCS, callback);
375 }
376 } finally {
377 Binder.restoreCallingIdentity(identity);
378 }
379 }
380 /**
381 * Unregister a previously registered IImsServiceFeatureCallback associated with an ImsFeature.
382 */
383 @Override
384 public void unregisterImsFeatureCallback(IImsServiceFeatureCallback callback) {
385 enforceModifyPermission();
386
387 final long identity = Binder.clearCallingIdentity();
388 try {
389 if (mImsResolver == null) return;
390 mImsResolver.unregisterImsFeatureCallback(callback);
391 } finally {
392 Binder.restoreCallingIdentity(identity);
393 }
394 }
395
396 /**
James.cf Linaf3183c2019-10-24 00:59:00 +0800397 * Make sure either called from same process as self (phone) or IPC caller has read privilege.
398 *
399 * @throws SecurityException if the caller does not have the required permission
400 */
401 private void enforceReadPrivilegedPermission(String message) {
402 mApp.enforceCallingOrSelfPermission(
403 android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, message);
404 }
405
406 /**
407 * Make sure the caller has the MODIFY_PHONE_STATE permission.
408 *
409 * @throws SecurityException if the caller does not have the required permission
410 */
411 private void enforceModifyPermission() {
412 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE, null);
413 }
James.cf Lincad981c2019-12-10 20:37:56 +0800414
415 /**
James.cf Lindc2d5422019-12-31 14:40:25 +0800416 * Retrieve ImsPhone instance.
James.cf Lincad981c2019-12-10 20:37:56 +0800417 *
418 * @param subId the subscription ID
James.cf Lindc2d5422019-12-31 14:40:25 +0800419 * @return The ImsPhone instance
420 * @throws ServiceSpecificException if getting ImsPhone instance failed.
James.cf Lincad981c2019-12-10 20:37:56 +0800421 */
James.cf Lindc2d5422019-12-31 14:40:25 +0800422 private ImsPhone getImsPhone(int subId) {
423 if (!ImsManager.isImsSupportedOnDevice(mApp)) {
424 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
425 "IMS is not available on device.");
426 }
James.cf Lincad981c2019-12-10 20:37:56 +0800427 Phone phone = PhoneGlobals.getPhone(subId);
428 if (phone == null) {
429 throw new ServiceSpecificException(ImsException.CODE_ERROR_INVALID_SUBSCRIPTION,
430 "Invalid subscription Id: " + subId);
431 }
432 ImsPhone imsPhone = (ImsPhone) phone.getImsPhone();
433 if (imsPhone == null) {
James.cf Lindc2d5422019-12-31 14:40:25 +0800434 throw new ServiceSpecificException(ImsException.CODE_ERROR_SERVICE_UNAVAILABLE,
435 "Cannot find ImsPhone instance: " + subId);
436 }
437 return imsPhone;
438 }
439
440 /**
441 * Retrieve RcsFeatureManager instance.
442 *
443 * @param subId the subscription ID
444 * @return The RcsFeatureManager instance
445 * @throws ServiceSpecificException if getting RcsFeatureManager instance failed.
446 */
Brad Ebingera68a4972020-01-30 17:31:23 -0800447 private RcsFeatureController getRcsFeatureController(int subId) {
James.cf Lindc2d5422019-12-31 14:40:25 +0800448 if (!ImsManager.isImsSupportedOnDevice(mApp)) {
James.cf Lincad981c2019-12-10 20:37:56 +0800449 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
James.cf Lindc2d5422019-12-31 14:40:25 +0800450 "IMS is not available on device.");
451 }
Brad Ebingera68a4972020-01-30 17:31:23 -0800452 if (mRcsService == null) {
453 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
454 "IMS is not available on device.");
455 }
James.cf Lindc2d5422019-12-31 14:40:25 +0800456 Phone phone = PhoneGlobals.getPhone(subId);
457 if (phone == null) {
458 throw new ServiceSpecificException(ImsException.CODE_ERROR_INVALID_SUBSCRIPTION,
459 "Invalid subscription Id: " + subId);
460 }
Brad Ebingera68a4972020-01-30 17:31:23 -0800461 int slotId = phone.getPhoneId();
462 RcsFeatureController c = mRcsService.getFeatureController(slotId);
463 if (c == null) {
Brad Ebinger036dc9e2020-02-06 15:49:06 -0800464 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
465 "The requested operation is not supported for subId " + subId);
James.cf Lincad981c2019-12-10 20:37:56 +0800466 }
Brad Ebingera68a4972020-01-30 17:31:23 -0800467 return c;
James.cf Lincad981c2019-12-10 20:37:56 +0800468 }
James.cf Linc9f35a42020-01-15 02:35:22 +0800469
470 void setRcsService(TelephonyRcsService rcsService) {
471 mRcsService = rcsService;
472 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800473}