blob: fd61936848126d507308461710e3e265c0a4847e [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;
Brad Ebingerb989c7c2020-09-23 17:03:48 -070045import com.android.services.telephony.rcs.SipTransportController;
James.cf Linc9f35a42020-01-15 02:35:22 +080046import com.android.services.telephony.rcs.TelephonyRcsService;
Brad Ebingera68a4972020-01-30 17:31:23 -080047import com.android.services.telephony.rcs.UserCapabilityExchangeImpl;
James.cf Lincad981c2019-12-10 20:37:56 +080048
James.cf Linaf3183c2019-10-24 00:59:00 +080049import java.util.List;
50
51/**
52 * Implementation of the IImsRcsController interface.
53 */
54public class ImsRcsController extends IImsRcsController.Stub {
55 private static final String TAG = "ImsRcsController";
56
57 /** The singleton instance. */
58 private static ImsRcsController sInstance;
59
60 private PhoneGlobals mApp;
James.cf Linc9f35a42020-01-15 02:35:22 +080061 private TelephonyRcsService mRcsService;
Brad Ebingere3ae65a2020-09-11 12:45:11 -070062 private ImsResolver mImsResolver;
James.cf Linaf3183c2019-10-24 00:59:00 +080063
64 /**
65 * Initialize the singleton ImsRcsController instance.
66 * This is only done once, at startup, from PhoneApp.onCreate().
67 */
68 static ImsRcsController init(PhoneGlobals app) {
69 synchronized (ImsRcsController.class) {
70 if (sInstance == null) {
71 sInstance = new ImsRcsController(app);
72 } else {
73 Log.wtf(TAG, "init() called multiple times! sInstance = " + sInstance);
74 }
75 return sInstance;
76 }
77 }
78
79 /** Private constructor; @see init() */
80 private ImsRcsController(PhoneGlobals app) {
81 Log.i(TAG, "ImsRcsController");
82 mApp = app;
Peter Wangc035ce42020-01-08 21:00:22 -080083 TelephonyFrameworkInitializer
84 .getTelephonyServiceManager().getTelephonyImsServiceRegisterer().register(this);
Brad Ebingere3ae65a2020-09-11 12:45:11 -070085 mImsResolver = mApp.getImsResolver();
James.cf Linaf3183c2019-10-24 00:59:00 +080086 }
87
James.cf Lincad981c2019-12-10 20:37:56 +080088 /**
Brad Ebingera68a4972020-01-30 17:31:23 -080089 * Register a {@link RegistrationManager.RegistrationCallback} to receive IMS network
90 * registration state.
James.cf Lindc2d5422019-12-31 14:40:25 +080091 */
92 @Override
Brad Ebingera68a4972020-01-30 17:31:23 -080093 public void registerImsRegistrationCallback(int subId, IImsRegistrationCallback callback) {
James.cf Lindc2d5422019-12-31 14:40:25 +080094 enforceReadPrivilegedPermission("registerImsRegistrationCallback");
95 final long token = Binder.clearCallingIdentity();
96 try {
Brad Ebingera68a4972020-01-30 17:31:23 -080097 getRcsFeatureController(subId).registerImsRegistrationCallback(subId, callback);
98 } catch (ImsException e) {
James.cf Lindc2d5422019-12-31 14:40:25 +080099 Log.e(TAG, "registerImsRegistrationCallback: sudId=" + subId + ", " + e.getMessage());
100 throw new ServiceSpecificException(e.getCode());
101 } finally {
102 Binder.restoreCallingIdentity(token);
103 }
104 }
105
106 /**
Brad Ebingera68a4972020-01-30 17:31:23 -0800107 * Removes an existing {@link RegistrationManager.RegistrationCallback}.
James.cf Lindc2d5422019-12-31 14:40:25 +0800108 */
109 @Override
110 public void unregisterImsRegistrationCallback(int subId, IImsRegistrationCallback callback) {
111 enforceReadPrivilegedPermission("unregisterImsRegistrationCallback");
112 final long token = Binder.clearCallingIdentity();
113 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800114 getRcsFeatureController(subId).unregisterImsRegistrationCallback(subId, callback);
James.cf Lindc2d5422019-12-31 14:40:25 +0800115 } catch (ServiceSpecificException e) {
116 Log.e(TAG, "unregisterImsRegistrationCallback: error=" + e.errorCode);
117 } finally {
118 Binder.restoreCallingIdentity(token);
119 }
120 }
121
122 /**
123 * Get the IMS service registration state for the RcsFeature associated with this sub id.
124 */
125 @Override
126 public void getImsRcsRegistrationState(int subId, IIntegerConsumer consumer) {
127 enforceReadPrivilegedPermission("getImsRcsRegistrationState");
128 final long token = Binder.clearCallingIdentity();
129 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800130 getRcsFeatureController(subId).getRegistrationState(regState -> {
James.cf Lindc2d5422019-12-31 14:40:25 +0800131 try {
132 consumer.accept((regState == null)
133 ? RegistrationManager.REGISTRATION_STATE_NOT_REGISTERED : regState);
134 } catch (RemoteException e) {
135 Log.w(TAG, "getImsRcsRegistrationState: callback is not available.");
136 }
137 });
138 } finally {
139 Binder.restoreCallingIdentity(token);
140 }
141 }
142
143 /**
144 * Gets the Transport Type associated with the current IMS RCS registration.
145 */
146 @Override
147 public void getImsRcsRegistrationTransportType(int subId, IIntegerConsumer consumer) {
148 enforceReadPrivilegedPermission("getImsRcsRegistrationTransportType");
149 final long token = Binder.clearCallingIdentity();
150 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800151 getRcsFeatureController(subId).getRegistrationTech(regTech -> {
James.cf Lindc2d5422019-12-31 14:40:25 +0800152 // Convert registration tech from ImsRegistrationImplBase -> RegistrationManager
153 int regTechConverted = (regTech == null)
154 ? ImsRegistrationImplBase.REGISTRATION_TECH_NONE : regTech;
155 regTechConverted = RegistrationManager.IMS_REG_TO_ACCESS_TYPE_MAP.get(
156 regTechConverted);
157 try {
158 consumer.accept(regTechConverted);
159 } catch (RemoteException e) {
160 Log.w(TAG, "getImsRcsRegistrationTransportType: callback is not available.");
161 }
162 });
163 } finally {
164 Binder.restoreCallingIdentity(token);
165 }
166 }
167
168 /**
James.cf Lincad981c2019-12-10 20:37:56 +0800169 * Register a capability callback which will provide RCS availability updates for the
170 * subscription specified.
171 *
172 * @param subId the subscription ID
173 * @param callback The ImsCapabilityCallback to be registered.
174 */
James.cf Linaf3183c2019-10-24 00:59:00 +0800175 @Override
Brad Ebingera68a4972020-01-30 17:31:23 -0800176 public void registerRcsAvailabilityCallback(int subId, IImsCapabilityCallback callback) {
James.cf Linaf3183c2019-10-24 00:59:00 +0800177 enforceReadPrivilegedPermission("registerRcsAvailabilityCallback");
James.cf Lincad981c2019-12-10 20:37:56 +0800178 final long token = Binder.clearCallingIdentity();
179 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800180 getRcsFeatureController(subId).registerRcsAvailabilityCallback(subId, callback);
181 } catch (ImsException e) {
James.cf Lincad981c2019-12-10 20:37:56 +0800182 Log.e(TAG, "registerRcsAvailabilityCallback: sudId=" + subId + ", " + e.getMessage());
183 throw new ServiceSpecificException(e.getCode());
184 } finally {
185 Binder.restoreCallingIdentity(token);
186 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800187 }
188
James.cf Lincad981c2019-12-10 20:37:56 +0800189 /**
190 * Remove the registered capability callback.
191 *
192 * @param subId the subscription ID
193 * @param callback The ImsCapabilityCallback to be removed.
194 */
James.cf Linaf3183c2019-10-24 00:59:00 +0800195 @Override
James.cf Lincad981c2019-12-10 20:37:56 +0800196 public void unregisterRcsAvailabilityCallback(int subId, IImsCapabilityCallback callback) {
James.cf Linaf3183c2019-10-24 00:59:00 +0800197 enforceReadPrivilegedPermission("unregisterRcsAvailabilityCallback");
James.cf Lincad981c2019-12-10 20:37:56 +0800198 final long token = Binder.clearCallingIdentity();
199 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800200 getRcsFeatureController(subId).unregisterRcsAvailabilityCallback(subId, callback);
James.cf Lincad981c2019-12-10 20:37:56 +0800201 } finally {
202 Binder.restoreCallingIdentity(token);
203 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800204 }
205
James.cf Lincdad3862020-02-25 15:55:03 +0800206 @Override
207 public void registerUcePublishStateCallback(int subId, IRcsUcePublishStateCallback c) {
208 enforceReadPrivilegedPermission("registerUcePublishStateCallback");
209 final long token = Binder.clearCallingIdentity();
210 try {
211 UserCapabilityExchangeImpl uce = getRcsFeatureController(subId).getFeature(
212 UserCapabilityExchangeImpl.class);
213 if (uce == null) {
214 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
215 "This subscription does not support UCE.");
216 }
217 uce.registerPublishStateCallback(c);
218 } finally {
219 Binder.restoreCallingIdentity(token);
220 }
221 }
222
223 @Override
224 public void unregisterUcePublishStateCallback(int subId, IRcsUcePublishStateCallback c) {
225 enforceReadPrivilegedPermission("unregisterUcePublishStateCallback");
226 final long token = Binder.clearCallingIdentity();
227 try {
228 UserCapabilityExchangeImpl uce = getRcsFeatureController(subId).getFeature(
229 UserCapabilityExchangeImpl.class);
230 if (uce == null) {
231 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
232 "This subscription does not support UCE.");
233 }
234 uce.unregisterUcePublishStateCallback(c);
235 } finally {
236 Binder.restoreCallingIdentity(token);
237 }
238 }
239
James.cf Lincad981c2019-12-10 20:37:56 +0800240 /**
241 * Query for the capability of an IMS RCS service
242 *
243 * @param subId the subscription ID
244 * @param capability the RCS capability to query.
245 * @param radioTech the radio tech that this capability failed for
246 * @return true if the RCS capability is capable for this subscription, false otherwise.
247 */
James.cf Linaf3183c2019-10-24 00:59:00 +0800248 @Override
249 public boolean isCapable(int subId,
James.cf Lincad981c2019-12-10 20:37:56 +0800250 @RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability,
251 @ImsRegistrationImplBase.ImsRegistrationTech int radioTech) {
James.cf Linaf3183c2019-10-24 00:59:00 +0800252 enforceReadPrivilegedPermission("isCapable");
James.cf Lincad981c2019-12-10 20:37:56 +0800253 final long token = Binder.clearCallingIdentity();
254 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800255 return getRcsFeatureController(subId).isCapable(capability, radioTech);
256 } catch (ImsException e) {
James.cf Lincad981c2019-12-10 20:37:56 +0800257 Log.e(TAG, "isCapable: sudId=" + subId
258 + ", capability=" + capability + ", " + e.getMessage());
259 return false;
260 } finally {
261 Binder.restoreCallingIdentity(token);
262 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800263 }
264
James.cf Lincad981c2019-12-10 20:37:56 +0800265 /**
266 * Query the availability of an IMS RCS capability.
267 *
268 * @param subId the subscription ID
269 * @param capability the RCS capability to query.
270 * @return true if the RCS capability is currently available for the associated subscription,
271 * false otherwise.
272 */
James.cf Linaf3183c2019-10-24 00:59:00 +0800273 @Override
274 public boolean isAvailable(int subId,
275 @RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability) {
276 enforceReadPrivilegedPermission("isAvailable");
James.cf Lincad981c2019-12-10 20:37:56 +0800277 final long token = Binder.clearCallingIdentity();
278 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800279 return getRcsFeatureController(subId).isAvailable(capability);
280 } catch (ImsException e) {
James.cf Lincad981c2019-12-10 20:37:56 +0800281 Log.e(TAG, "isAvailable: sudId=" + subId
282 + ", capability=" + capability + ", " + e.getMessage());
283 return false;
284 } finally {
285 Binder.restoreCallingIdentity(token);
286 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800287 }
288
289 @Override
Brad Ebinger8b79edc2020-02-27 19:13:24 -0800290 public void requestCapabilities(int subId, String callingPackage, String callingFeatureId,
291 List<Uri> contactNumbers, IRcsUceControllerCallback c) {
James.cf Linaf3183c2019-10-24 00:59:00 +0800292 enforceReadPrivilegedPermission("requestCapabilities");
Brad Ebinger8b79edc2020-02-27 19:13:24 -0800293 if (!isUceSettingEnabled(subId, callingPackage, callingFeatureId)) {
294 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
295 "The user has not enabled UCE for this subscription.");
296 }
Brad Ebingera68a4972020-01-30 17:31:23 -0800297 final long token = Binder.clearCallingIdentity();
298 try {
299 UserCapabilityExchangeImpl uce = getRcsFeatureController(subId).getFeature(
300 UserCapabilityExchangeImpl.class);
301 if (uce == null) {
302 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
303 "This subscription does not support UCE.");
304 }
305 uce.requestCapabilities(contactNumbers, c);
306 } finally {
307 Binder.restoreCallingIdentity(token);
Brad Ebinger1aa94992020-01-22 14:17:23 -0800308 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800309 }
310
311 @Override
312 public int getUcePublishState(int subId) {
313 enforceReadPrivilegedPermission("getUcePublishState");
Brad Ebingera68a4972020-01-30 17:31:23 -0800314 final long token = Binder.clearCallingIdentity();
315 try {
316 UserCapabilityExchangeImpl uce = getRcsFeatureController(subId).getFeature(
317 UserCapabilityExchangeImpl.class);
318 if (uce == null) {
319 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
320 "This subscription does not support UCE.");
321 }
322 return uce.getUcePublishState();
323 } finally {
324 Binder.restoreCallingIdentity(token);
Brad Ebinger1aa94992020-01-22 14:17:23 -0800325 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800326 }
327
328 @Override
Brad Ebinger8b79edc2020-02-27 19:13:24 -0800329 public boolean isUceSettingEnabled(int subId, String callingPackage, String callingFeatureId) {
330 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
331 mApp, subId, callingPackage, callingFeatureId, "isUceSettingEnabled")) {
332 Log.w(TAG, "isUceSettingEnabled: READ_PHONE_STATE app op disabled when accessing "
333 + "isUceSettingEnabled");
334 return false;
335 }
336 final long token = Binder.clearCallingIdentity();
337 try {
338 return SubscriptionManager.getBooleanSubscriptionProperty(subId,
339 SubscriptionManager.IMS_RCS_UCE_ENABLED, false /*defaultValue*/, mApp);
340 } finally {
341 Binder.restoreCallingIdentity(token);
342 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800343 }
344
345 @Override
346 public void setUceSettingEnabled(int subId, boolean isEnabled) {
347 enforceModifyPermission();
Brad Ebinger8b79edc2020-02-27 19:13:24 -0800348 final long token = Binder.clearCallingIdentity();
349 try {
350 SubscriptionManager.setSubscriptionProperty(subId,
351 SubscriptionManager.IMS_RCS_UCE_ENABLED, (isEnabled ? "1" : "0"));
352 } finally {
353 Binder.restoreCallingIdentity(token);
354 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800355 }
356
Brad Ebingerb989c7c2020-09-23 17:03:48 -0700357 @Override
358 public boolean isSipDelegateSupported(int subId) {
359 enforceReadPrivilegedPermission("isSipDelegateSupported");
360 final long token = Binder.clearCallingIdentity();
361 try {
362 SipTransportController transport = getRcsFeatureController(subId).getFeature(
363 SipTransportController.class);
364 if (transport == null) {
365 return false;
366 }
367 return transport.isSupported(subId);
368 } catch (ImsException e) {
369 throw new ServiceSpecificException(e.getCode(), e.getMessage());
370 } catch (ServiceSpecificException e) {
371 if (e.errorCode == ImsException.CODE_ERROR_UNSUPPORTED_OPERATION) {
372 return false;
373 }
374 throw e;
375 } finally {
376 Binder.restoreCallingIdentity(token);
377 }
378 }
379
James.cf Linaf3183c2019-10-24 00:59:00 +0800380 /**
Brad Ebingere3ae65a2020-09-11 12:45:11 -0700381 * Registers for updates to the RcsFeature connection through the IImsServiceFeatureCallback
382 * callback.
383 */
384 @Override
Brad Ebinger6366ce92020-10-01 13:51:05 -0700385 public void registerRcsFeatureCallback(int slotId, IImsServiceFeatureCallback callback) {
Brad Ebingere3ae65a2020-09-11 12:45:11 -0700386 enforceModifyPermission();
387
388 final long identity = Binder.clearCallingIdentity();
389 try {
390 if (mImsResolver == null) {
391 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
392 "Device does not support IMS");
393 }
Brad Ebinger6366ce92020-10-01 13:51:05 -0700394 mImsResolver.listenForFeature(slotId, ImsFeature.FEATURE_RCS, callback);
Brad Ebingere3ae65a2020-09-11 12:45:11 -0700395 } finally {
396 Binder.restoreCallingIdentity(identity);
397 }
398 }
Brad Ebinger6366ce92020-10-01 13:51:05 -0700399
Brad Ebingere3ae65a2020-09-11 12:45:11 -0700400 /**
401 * Unregister a previously registered IImsServiceFeatureCallback associated with an ImsFeature.
402 */
403 @Override
404 public void unregisterImsFeatureCallback(IImsServiceFeatureCallback callback) {
405 enforceModifyPermission();
406
407 final long identity = Binder.clearCallingIdentity();
408 try {
409 if (mImsResolver == null) return;
410 mImsResolver.unregisterImsFeatureCallback(callback);
411 } finally {
412 Binder.restoreCallingIdentity(identity);
413 }
414 }
415
416 /**
James.cf Linaf3183c2019-10-24 00:59:00 +0800417 * Make sure either called from same process as self (phone) or IPC caller has read privilege.
418 *
419 * @throws SecurityException if the caller does not have the required permission
420 */
421 private void enforceReadPrivilegedPermission(String message) {
422 mApp.enforceCallingOrSelfPermission(
423 android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, message);
424 }
425
426 /**
427 * Make sure the caller has the MODIFY_PHONE_STATE permission.
428 *
429 * @throws SecurityException if the caller does not have the required permission
430 */
431 private void enforceModifyPermission() {
432 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE, null);
433 }
James.cf Lincad981c2019-12-10 20:37:56 +0800434
435 /**
James.cf Lindc2d5422019-12-31 14:40:25 +0800436 * Retrieve ImsPhone instance.
James.cf Lincad981c2019-12-10 20:37:56 +0800437 *
438 * @param subId the subscription ID
James.cf Lindc2d5422019-12-31 14:40:25 +0800439 * @return The ImsPhone instance
440 * @throws ServiceSpecificException if getting ImsPhone instance failed.
James.cf Lincad981c2019-12-10 20:37:56 +0800441 */
James.cf Lindc2d5422019-12-31 14:40:25 +0800442 private ImsPhone getImsPhone(int subId) {
443 if (!ImsManager.isImsSupportedOnDevice(mApp)) {
444 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
445 "IMS is not available on device.");
446 }
James.cf Lincad981c2019-12-10 20:37:56 +0800447 Phone phone = PhoneGlobals.getPhone(subId);
448 if (phone == null) {
449 throw new ServiceSpecificException(ImsException.CODE_ERROR_INVALID_SUBSCRIPTION,
450 "Invalid subscription Id: " + subId);
451 }
452 ImsPhone imsPhone = (ImsPhone) phone.getImsPhone();
453 if (imsPhone == null) {
James.cf Lindc2d5422019-12-31 14:40:25 +0800454 throw new ServiceSpecificException(ImsException.CODE_ERROR_SERVICE_UNAVAILABLE,
455 "Cannot find ImsPhone instance: " + subId);
456 }
457 return imsPhone;
458 }
459
460 /**
461 * Retrieve RcsFeatureManager instance.
462 *
463 * @param subId the subscription ID
464 * @return The RcsFeatureManager instance
465 * @throws ServiceSpecificException if getting RcsFeatureManager instance failed.
466 */
Brad Ebingera68a4972020-01-30 17:31:23 -0800467 private RcsFeatureController getRcsFeatureController(int subId) {
James.cf Lindc2d5422019-12-31 14:40:25 +0800468 if (!ImsManager.isImsSupportedOnDevice(mApp)) {
James.cf Lincad981c2019-12-10 20:37:56 +0800469 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
James.cf Lindc2d5422019-12-31 14:40:25 +0800470 "IMS is not available on device.");
471 }
Brad Ebingera68a4972020-01-30 17:31:23 -0800472 if (mRcsService == null) {
473 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
474 "IMS is not available on device.");
475 }
James.cf Lindc2d5422019-12-31 14:40:25 +0800476 Phone phone = PhoneGlobals.getPhone(subId);
477 if (phone == null) {
478 throw new ServiceSpecificException(ImsException.CODE_ERROR_INVALID_SUBSCRIPTION,
479 "Invalid subscription Id: " + subId);
480 }
Brad Ebingera68a4972020-01-30 17:31:23 -0800481 int slotId = phone.getPhoneId();
482 RcsFeatureController c = mRcsService.getFeatureController(slotId);
483 if (c == null) {
Brad Ebinger036dc9e2020-02-06 15:49:06 -0800484 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
485 "The requested operation is not supported for subId " + subId);
James.cf Lincad981c2019-12-10 20:37:56 +0800486 }
Brad Ebingera68a4972020-01-30 17:31:23 -0800487 return c;
James.cf Lincad981c2019-12-10 20:37:56 +0800488 }
James.cf Linc9f35a42020-01-15 02:35:22 +0800489
490 void setRcsService(TelephonyRcsService rcsService) {
491 mRcsService = rcsService;
492 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800493}