blob: e415122662e7e918c174ecb573ec010d9d6a335d [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 Lin99a360d2020-11-04 10:48:37 +080026import android.telephony.ims.RcsUceAdapter.PublishState;
James.cf Lindc2d5422019-12-31 14:40:25 +080027import android.telephony.ims.RegistrationManager;
James.cf Linaf3183c2019-10-24 00:59:00 +080028import android.telephony.ims.aidl.IImsCapabilityCallback;
29import android.telephony.ims.aidl.IImsRcsController;
James.cf Lindc2d5422019-12-31 14:40:25 +080030import android.telephony.ims.aidl.IImsRegistrationCallback;
James.cf Linaf3183c2019-10-24 00:59:00 +080031import android.telephony.ims.aidl.IRcsUceControllerCallback;
James.cf Lincdad3862020-02-25 15:55:03 +080032import android.telephony.ims.aidl.IRcsUcePublishStateCallback;
Brad Ebingere3ae65a2020-09-11 12:45:11 -070033import android.telephony.ims.feature.ImsFeature;
James.cf Linaf3183c2019-10-24 00:59:00 +080034import android.telephony.ims.feature.RcsFeature;
James.cf Lincad981c2019-12-10 20:37:56 +080035import android.telephony.ims.stub.ImsRegistrationImplBase;
James.cf Linaf3183c2019-10-24 00:59:00 +080036import android.util.Log;
37
James.cf Lindc2d5422019-12-31 14:40:25 +080038import com.android.ims.ImsManager;
Brad Ebingere3ae65a2020-09-11 12:45:11 -070039import com.android.ims.internal.IImsServiceFeatureCallback;
James.cf Lindc2d5422019-12-31 14:40:25 +080040import com.android.internal.telephony.IIntegerConsumer;
James.cf Lincad981c2019-12-10 20:37:56 +080041import com.android.internal.telephony.Phone;
Brad Ebinger8b79edc2020-02-27 19:13:24 -080042import com.android.internal.telephony.TelephonyPermissions;
Brad Ebingere3ae65a2020-09-11 12:45:11 -070043import com.android.internal.telephony.ims.ImsResolver;
James.cf Lincad981c2019-12-10 20:37:56 +080044import com.android.internal.telephony.imsphone.ImsPhone;
Brad Ebingera68a4972020-01-30 17:31:23 -080045import com.android.services.telephony.rcs.RcsFeatureController;
Brad Ebingerb989c7c2020-09-23 17:03:48 -070046import com.android.services.telephony.rcs.SipTransportController;
James.cf Linc9f35a42020-01-15 02:35:22 +080047import com.android.services.telephony.rcs.TelephonyRcsService;
James.cf Lin99a360d2020-11-04 10:48:37 +080048import com.android.services.telephony.rcs.UceControllerManager;
James.cf Lincad981c2019-12-10 20:37:56 +080049
James.cf Linaf3183c2019-10-24 00:59:00 +080050import java.util.List;
51
52/**
53 * Implementation of the IImsRcsController interface.
54 */
55public class ImsRcsController extends IImsRcsController.Stub {
56 private static final String TAG = "ImsRcsController";
57
58 /** The singleton instance. */
59 private static ImsRcsController sInstance;
60
61 private PhoneGlobals mApp;
James.cf Linc9f35a42020-01-15 02:35:22 +080062 private TelephonyRcsService mRcsService;
Brad Ebingere3ae65a2020-09-11 12:45:11 -070063 private ImsResolver mImsResolver;
James.cf Linaf3183c2019-10-24 00:59:00 +080064
65 /**
66 * Initialize the singleton ImsRcsController instance.
67 * This is only done once, at startup, from PhoneApp.onCreate().
68 */
69 static ImsRcsController init(PhoneGlobals app) {
70 synchronized (ImsRcsController.class) {
71 if (sInstance == null) {
72 sInstance = new ImsRcsController(app);
73 } else {
74 Log.wtf(TAG, "init() called multiple times! sInstance = " + sInstance);
75 }
76 return sInstance;
77 }
78 }
79
80 /** Private constructor; @see init() */
81 private ImsRcsController(PhoneGlobals app) {
82 Log.i(TAG, "ImsRcsController");
83 mApp = app;
Peter Wangc035ce42020-01-08 21:00:22 -080084 TelephonyFrameworkInitializer
85 .getTelephonyServiceManager().getTelephonyImsServiceRegisterer().register(this);
Brad Ebingere3ae65a2020-09-11 12:45:11 -070086 mImsResolver = mApp.getImsResolver();
James.cf Linaf3183c2019-10-24 00:59:00 +080087 }
88
James.cf Lincad981c2019-12-10 20:37:56 +080089 /**
Brad Ebingera68a4972020-01-30 17:31:23 -080090 * Register a {@link RegistrationManager.RegistrationCallback} to receive IMS network
91 * registration state.
James.cf Lindc2d5422019-12-31 14:40:25 +080092 */
93 @Override
Brad Ebingera68a4972020-01-30 17:31:23 -080094 public void registerImsRegistrationCallback(int subId, IImsRegistrationCallback callback) {
James.cf Lindc2d5422019-12-31 14:40:25 +080095 enforceReadPrivilegedPermission("registerImsRegistrationCallback");
96 final long token = Binder.clearCallingIdentity();
97 try {
Brad Ebingera68a4972020-01-30 17:31:23 -080098 getRcsFeatureController(subId).registerImsRegistrationCallback(subId, callback);
99 } catch (ImsException e) {
James.cf Lindc2d5422019-12-31 14:40:25 +0800100 Log.e(TAG, "registerImsRegistrationCallback: sudId=" + subId + ", " + e.getMessage());
101 throw new ServiceSpecificException(e.getCode());
102 } finally {
103 Binder.restoreCallingIdentity(token);
104 }
105 }
106
107 /**
Brad Ebingera68a4972020-01-30 17:31:23 -0800108 * Removes an existing {@link RegistrationManager.RegistrationCallback}.
James.cf Lindc2d5422019-12-31 14:40:25 +0800109 */
110 @Override
111 public void unregisterImsRegistrationCallback(int subId, IImsRegistrationCallback callback) {
112 enforceReadPrivilegedPermission("unregisterImsRegistrationCallback");
113 final long token = Binder.clearCallingIdentity();
114 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800115 getRcsFeatureController(subId).unregisterImsRegistrationCallback(subId, callback);
James.cf Lindc2d5422019-12-31 14:40:25 +0800116 } catch (ServiceSpecificException e) {
117 Log.e(TAG, "unregisterImsRegistrationCallback: error=" + e.errorCode);
118 } finally {
119 Binder.restoreCallingIdentity(token);
120 }
121 }
122
123 /**
124 * Get the IMS service registration state for the RcsFeature associated with this sub id.
125 */
126 @Override
127 public void getImsRcsRegistrationState(int subId, IIntegerConsumer consumer) {
128 enforceReadPrivilegedPermission("getImsRcsRegistrationState");
129 final long token = Binder.clearCallingIdentity();
130 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800131 getRcsFeatureController(subId).getRegistrationState(regState -> {
James.cf Lindc2d5422019-12-31 14:40:25 +0800132 try {
133 consumer.accept((regState == null)
134 ? RegistrationManager.REGISTRATION_STATE_NOT_REGISTERED : regState);
135 } catch (RemoteException e) {
136 Log.w(TAG, "getImsRcsRegistrationState: callback is not available.");
137 }
138 });
139 } finally {
140 Binder.restoreCallingIdentity(token);
141 }
142 }
143
144 /**
145 * Gets the Transport Type associated with the current IMS RCS registration.
146 */
147 @Override
148 public void getImsRcsRegistrationTransportType(int subId, IIntegerConsumer consumer) {
149 enforceReadPrivilegedPermission("getImsRcsRegistrationTransportType");
150 final long token = Binder.clearCallingIdentity();
151 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800152 getRcsFeatureController(subId).getRegistrationTech(regTech -> {
James.cf Lindc2d5422019-12-31 14:40:25 +0800153 // Convert registration tech from ImsRegistrationImplBase -> RegistrationManager
154 int regTechConverted = (regTech == null)
155 ? ImsRegistrationImplBase.REGISTRATION_TECH_NONE : regTech;
156 regTechConverted = RegistrationManager.IMS_REG_TO_ACCESS_TYPE_MAP.get(
157 regTechConverted);
158 try {
159 consumer.accept(regTechConverted);
160 } catch (RemoteException e) {
161 Log.w(TAG, "getImsRcsRegistrationTransportType: callback is not available.");
162 }
163 });
164 } finally {
165 Binder.restoreCallingIdentity(token);
166 }
167 }
168
169 /**
James.cf Lincad981c2019-12-10 20:37:56 +0800170 * Register a capability callback which will provide RCS availability updates for the
171 * subscription specified.
172 *
173 * @param subId the subscription ID
174 * @param callback The ImsCapabilityCallback to be registered.
175 */
James.cf Linaf3183c2019-10-24 00:59:00 +0800176 @Override
Brad Ebingera68a4972020-01-30 17:31:23 -0800177 public void registerRcsAvailabilityCallback(int subId, IImsCapabilityCallback callback) {
James.cf Linaf3183c2019-10-24 00:59:00 +0800178 enforceReadPrivilegedPermission("registerRcsAvailabilityCallback");
James.cf Lincad981c2019-12-10 20:37:56 +0800179 final long token = Binder.clearCallingIdentity();
180 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800181 getRcsFeatureController(subId).registerRcsAvailabilityCallback(subId, callback);
182 } catch (ImsException e) {
James.cf Lincad981c2019-12-10 20:37:56 +0800183 Log.e(TAG, "registerRcsAvailabilityCallback: sudId=" + subId + ", " + e.getMessage());
184 throw new ServiceSpecificException(e.getCode());
185 } finally {
186 Binder.restoreCallingIdentity(token);
187 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800188 }
189
James.cf Lincad981c2019-12-10 20:37:56 +0800190 /**
191 * Remove the registered capability callback.
192 *
193 * @param subId the subscription ID
194 * @param callback The ImsCapabilityCallback to be removed.
195 */
James.cf Linaf3183c2019-10-24 00:59:00 +0800196 @Override
James.cf Lincad981c2019-12-10 20:37:56 +0800197 public void unregisterRcsAvailabilityCallback(int subId, IImsCapabilityCallback callback) {
James.cf Linaf3183c2019-10-24 00:59:00 +0800198 enforceReadPrivilegedPermission("unregisterRcsAvailabilityCallback");
James.cf Lincad981c2019-12-10 20:37:56 +0800199 final long token = Binder.clearCallingIdentity();
200 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800201 getRcsFeatureController(subId).unregisterRcsAvailabilityCallback(subId, callback);
James.cf Lincad981c2019-12-10 20:37:56 +0800202 } finally {
203 Binder.restoreCallingIdentity(token);
204 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800205 }
206
James.cf Lincad981c2019-12-10 20:37:56 +0800207 /**
208 * Query for the capability of an IMS RCS service
209 *
210 * @param subId the subscription ID
211 * @param capability the RCS capability to query.
212 * @param radioTech the radio tech that this capability failed for
213 * @return true if the RCS capability is capable for this subscription, false otherwise.
214 */
James.cf Linaf3183c2019-10-24 00:59:00 +0800215 @Override
216 public boolean isCapable(int subId,
James.cf Lincad981c2019-12-10 20:37:56 +0800217 @RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability,
218 @ImsRegistrationImplBase.ImsRegistrationTech int radioTech) {
James.cf Linaf3183c2019-10-24 00:59:00 +0800219 enforceReadPrivilegedPermission("isCapable");
James.cf Lincad981c2019-12-10 20:37:56 +0800220 final long token = Binder.clearCallingIdentity();
221 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800222 return getRcsFeatureController(subId).isCapable(capability, radioTech);
223 } catch (ImsException e) {
James.cf Lincad981c2019-12-10 20:37:56 +0800224 Log.e(TAG, "isCapable: sudId=" + subId
225 + ", capability=" + capability + ", " + e.getMessage());
226 return false;
227 } finally {
228 Binder.restoreCallingIdentity(token);
229 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800230 }
231
James.cf Lincad981c2019-12-10 20:37:56 +0800232 /**
233 * Query the availability of an IMS RCS capability.
234 *
235 * @param subId the subscription ID
236 * @param capability the RCS capability to query.
237 * @return true if the RCS capability is currently available for the associated subscription,
238 * false otherwise.
239 */
James.cf Linaf3183c2019-10-24 00:59:00 +0800240 @Override
241 public boolean isAvailable(int subId,
242 @RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability) {
243 enforceReadPrivilegedPermission("isAvailable");
James.cf Lincad981c2019-12-10 20:37:56 +0800244 final long token = Binder.clearCallingIdentity();
245 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800246 return getRcsFeatureController(subId).isAvailable(capability);
247 } catch (ImsException e) {
James.cf Lincad981c2019-12-10 20:37:56 +0800248 Log.e(TAG, "isAvailable: sudId=" + subId
249 + ", capability=" + capability + ", " + e.getMessage());
250 return false;
251 } finally {
252 Binder.restoreCallingIdentity(token);
253 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800254 }
255
256 @Override
Brad Ebinger8b79edc2020-02-27 19:13:24 -0800257 public void requestCapabilities(int subId, String callingPackage, String callingFeatureId,
258 List<Uri> contactNumbers, IRcsUceControllerCallback c) {
James.cf Linaf3183c2019-10-24 00:59:00 +0800259 enforceReadPrivilegedPermission("requestCapabilities");
Brad Ebinger8b79edc2020-02-27 19:13:24 -0800260 if (!isUceSettingEnabled(subId, callingPackage, callingFeatureId)) {
261 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
262 "The user has not enabled UCE for this subscription.");
263 }
Brad Ebingera68a4972020-01-30 17:31:23 -0800264 final long token = Binder.clearCallingIdentity();
265 try {
James.cf Lin99a360d2020-11-04 10:48:37 +0800266 UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
267 UceControllerManager.class);
268 if (uceCtrlManager == null) {
Brad Ebingera68a4972020-01-30 17:31:23 -0800269 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
270 "This subscription does not support UCE.");
271 }
James.cf Lin99a360d2020-11-04 10:48:37 +0800272 uceCtrlManager.requestCapabilities(contactNumbers, c);
273 } catch (ImsException e) {
274 throw new ServiceSpecificException(e.getCode(), e.getMessage());
Brad Ebingera68a4972020-01-30 17:31:23 -0800275 } finally {
276 Binder.restoreCallingIdentity(token);
Brad Ebinger1aa94992020-01-22 14:17:23 -0800277 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800278 }
279
280 @Override
James.cf Lin64e91212020-10-30 01:09:52 +0800281 public void requestNetworkAvailability(int subId, String callingPackage,
282 String callingFeatureId, Uri contactNumber, IRcsUceControllerCallback c) {
283 enforceReadPrivilegedPermission("requestNetworkAvailability");
284 if (!isUceSettingEnabled(subId, callingPackage, callingFeatureId)) {
285 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
286 "The user has not enabled UCE for this subscription.");
287 }
Brad Ebingera68a4972020-01-30 17:31:23 -0800288 final long token = Binder.clearCallingIdentity();
289 try {
James.cf Lin99a360d2020-11-04 10:48:37 +0800290 UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
291 UceControllerManager.class);
292 if (uceCtrlManager == null) {
Brad Ebingera68a4972020-01-30 17:31:23 -0800293 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
294 "This subscription does not support UCE.");
295 }
James.cf Lin99a360d2020-11-04 10:48:37 +0800296 uceCtrlManager.requestNetworkAvailability(contactNumber, c);
297 } catch (ImsException e) {
298 throw new ServiceSpecificException(e.getCode(), e.getMessage());
299 } finally {
300 Binder.restoreCallingIdentity(token);
301 }
302 }
303
304 @Override
305 public @PublishState int getUcePublishState(int subId) {
306 enforceReadPrivilegedPermission("getUcePublishState");
307 final long token = Binder.clearCallingIdentity();
308 try {
309 UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
310 UceControllerManager.class);
311 if (uceCtrlManager == null) {
312 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
313 "This subscription does not support UCE.");
314 }
315 return uceCtrlManager.getUcePublishState();
316 } catch (ImsException e) {
317 throw new ServiceSpecificException(e.getCode(), e.getMessage());
318 } finally {
319 Binder.restoreCallingIdentity(token);
320 }
321 }
322
323 @Override
324 public void registerUcePublishStateCallback(int subId, IRcsUcePublishStateCallback c) {
325 enforceReadPrivilegedPermission("registerUcePublishStateCallback");
326 final long token = Binder.clearCallingIdentity();
327 try {
328 UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
329 UceControllerManager.class);
330 if (uceCtrlManager == null) {
331 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
332 "This subscription does not support UCE.");
333 }
334 uceCtrlManager.registerPublishStateCallback(c);
335 } catch (ImsException e) {
336 throw new ServiceSpecificException(e.getCode(), e.getMessage());
337 } finally {
338 Binder.restoreCallingIdentity(token);
339 }
340 }
341
342 @Override
343 public void unregisterUcePublishStateCallback(int subId, IRcsUcePublishStateCallback c) {
344 enforceReadPrivilegedPermission("unregisterUcePublishStateCallback");
345 final long token = Binder.clearCallingIdentity();
346 try {
347 UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
348 UceControllerManager.class);
349 if (uceCtrlManager == null) {
350 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
351 "This subscription does not support UCE.");
352 }
353 uceCtrlManager.unregisterPublishStateCallback(c);
Brad Ebingera68a4972020-01-30 17:31:23 -0800354 } finally {
355 Binder.restoreCallingIdentity(token);
Brad Ebinger1aa94992020-01-22 14:17:23 -0800356 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800357 }
358
359 @Override
Brad Ebinger8b79edc2020-02-27 19:13:24 -0800360 public boolean isUceSettingEnabled(int subId, String callingPackage, String callingFeatureId) {
361 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
362 mApp, subId, callingPackage, callingFeatureId, "isUceSettingEnabled")) {
363 Log.w(TAG, "isUceSettingEnabled: READ_PHONE_STATE app op disabled when accessing "
364 + "isUceSettingEnabled");
365 return false;
366 }
367 final long token = Binder.clearCallingIdentity();
368 try {
369 return SubscriptionManager.getBooleanSubscriptionProperty(subId,
370 SubscriptionManager.IMS_RCS_UCE_ENABLED, false /*defaultValue*/, mApp);
371 } finally {
372 Binder.restoreCallingIdentity(token);
373 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800374 }
375
376 @Override
377 public void setUceSettingEnabled(int subId, boolean isEnabled) {
378 enforceModifyPermission();
Brad Ebinger8b79edc2020-02-27 19:13:24 -0800379 final long token = Binder.clearCallingIdentity();
380 try {
381 SubscriptionManager.setSubscriptionProperty(subId,
382 SubscriptionManager.IMS_RCS_UCE_ENABLED, (isEnabled ? "1" : "0"));
383 } finally {
384 Binder.restoreCallingIdentity(token);
385 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800386 }
387
Brad Ebingerb989c7c2020-09-23 17:03:48 -0700388 @Override
389 public boolean isSipDelegateSupported(int subId) {
390 enforceReadPrivilegedPermission("isSipDelegateSupported");
391 final long token = Binder.clearCallingIdentity();
392 try {
393 SipTransportController transport = getRcsFeatureController(subId).getFeature(
394 SipTransportController.class);
395 if (transport == null) {
396 return false;
397 }
398 return transport.isSupported(subId);
399 } catch (ImsException e) {
400 throw new ServiceSpecificException(e.getCode(), e.getMessage());
401 } catch (ServiceSpecificException e) {
402 if (e.errorCode == ImsException.CODE_ERROR_UNSUPPORTED_OPERATION) {
403 return false;
404 }
405 throw e;
406 } finally {
407 Binder.restoreCallingIdentity(token);
408 }
409 }
410
James.cf Linaf3183c2019-10-24 00:59:00 +0800411 /**
Brad Ebingere3ae65a2020-09-11 12:45:11 -0700412 * Registers for updates to the RcsFeature connection through the IImsServiceFeatureCallback
413 * callback.
414 */
415 @Override
Brad Ebinger6366ce92020-10-01 13:51:05 -0700416 public void registerRcsFeatureCallback(int slotId, IImsServiceFeatureCallback callback) {
Brad Ebingere3ae65a2020-09-11 12:45:11 -0700417 enforceModifyPermission();
418
419 final long identity = Binder.clearCallingIdentity();
420 try {
421 if (mImsResolver == null) {
422 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
423 "Device does not support IMS");
424 }
Brad Ebinger6366ce92020-10-01 13:51:05 -0700425 mImsResolver.listenForFeature(slotId, ImsFeature.FEATURE_RCS, callback);
Brad Ebingere3ae65a2020-09-11 12:45:11 -0700426 } finally {
427 Binder.restoreCallingIdentity(identity);
428 }
429 }
Brad Ebinger6366ce92020-10-01 13:51:05 -0700430
Brad Ebingere3ae65a2020-09-11 12:45:11 -0700431 /**
432 * Unregister a previously registered IImsServiceFeatureCallback associated with an ImsFeature.
433 */
434 @Override
435 public void unregisterImsFeatureCallback(IImsServiceFeatureCallback callback) {
436 enforceModifyPermission();
437
438 final long identity = Binder.clearCallingIdentity();
439 try {
440 if (mImsResolver == null) return;
441 mImsResolver.unregisterImsFeatureCallback(callback);
442 } finally {
443 Binder.restoreCallingIdentity(identity);
444 }
445 }
446
447 /**
James.cf Linaf3183c2019-10-24 00:59:00 +0800448 * Make sure either called from same process as self (phone) or IPC caller has read privilege.
449 *
450 * @throws SecurityException if the caller does not have the required permission
451 */
452 private void enforceReadPrivilegedPermission(String message) {
453 mApp.enforceCallingOrSelfPermission(
454 android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, message);
455 }
456
457 /**
458 * Make sure the caller has the MODIFY_PHONE_STATE permission.
459 *
460 * @throws SecurityException if the caller does not have the required permission
461 */
462 private void enforceModifyPermission() {
463 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE, null);
464 }
James.cf Lincad981c2019-12-10 20:37:56 +0800465
466 /**
James.cf Lindc2d5422019-12-31 14:40:25 +0800467 * Retrieve ImsPhone instance.
James.cf Lincad981c2019-12-10 20:37:56 +0800468 *
469 * @param subId the subscription ID
James.cf Lindc2d5422019-12-31 14:40:25 +0800470 * @return The ImsPhone instance
471 * @throws ServiceSpecificException if getting ImsPhone instance failed.
James.cf Lincad981c2019-12-10 20:37:56 +0800472 */
James.cf Lindc2d5422019-12-31 14:40:25 +0800473 private ImsPhone getImsPhone(int subId) {
474 if (!ImsManager.isImsSupportedOnDevice(mApp)) {
475 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
476 "IMS is not available on device.");
477 }
James.cf Lincad981c2019-12-10 20:37:56 +0800478 Phone phone = PhoneGlobals.getPhone(subId);
479 if (phone == null) {
480 throw new ServiceSpecificException(ImsException.CODE_ERROR_INVALID_SUBSCRIPTION,
481 "Invalid subscription Id: " + subId);
482 }
483 ImsPhone imsPhone = (ImsPhone) phone.getImsPhone();
484 if (imsPhone == null) {
James.cf Lindc2d5422019-12-31 14:40:25 +0800485 throw new ServiceSpecificException(ImsException.CODE_ERROR_SERVICE_UNAVAILABLE,
486 "Cannot find ImsPhone instance: " + subId);
487 }
488 return imsPhone;
489 }
490
491 /**
492 * Retrieve RcsFeatureManager instance.
493 *
494 * @param subId the subscription ID
495 * @return The RcsFeatureManager instance
496 * @throws ServiceSpecificException if getting RcsFeatureManager instance failed.
497 */
Brad Ebingera68a4972020-01-30 17:31:23 -0800498 private RcsFeatureController getRcsFeatureController(int subId) {
James.cf Lindc2d5422019-12-31 14:40:25 +0800499 if (!ImsManager.isImsSupportedOnDevice(mApp)) {
James.cf Lincad981c2019-12-10 20:37:56 +0800500 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
James.cf Lindc2d5422019-12-31 14:40:25 +0800501 "IMS is not available on device.");
502 }
Brad Ebingera68a4972020-01-30 17:31:23 -0800503 if (mRcsService == null) {
504 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
505 "IMS is not available on device.");
506 }
James.cf Lindc2d5422019-12-31 14:40:25 +0800507 Phone phone = PhoneGlobals.getPhone(subId);
508 if (phone == null) {
509 throw new ServiceSpecificException(ImsException.CODE_ERROR_INVALID_SUBSCRIPTION,
510 "Invalid subscription Id: " + subId);
511 }
Brad Ebingera68a4972020-01-30 17:31:23 -0800512 int slotId = phone.getPhoneId();
513 RcsFeatureController c = mRcsService.getFeatureController(slotId);
514 if (c == null) {
Brad Ebinger036dc9e2020-02-06 15:49:06 -0800515 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
516 "The requested operation is not supported for subId " + subId);
James.cf Lincad981c2019-12-10 20:37:56 +0800517 }
Brad Ebingera68a4972020-01-30 17:31:23 -0800518 return c;
James.cf Lincad981c2019-12-10 20:37:56 +0800519 }
James.cf Linc9f35a42020-01-15 02:35:22 +0800520
521 void setRcsService(TelephonyRcsService rcsService) {
522 mRcsService = rcsService;
523 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800524}