blob: 93340786d26e47b106e7cf0e139f64c7f57ab962 [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 Ebinger63b6f5a2020-10-27 11:43:35 -070019import android.content.pm.PackageManager;
James.cf Linaf3183c2019-10-24 00:59:00 +080020import android.net.Uri;
James.cf Lincad981c2019-12-10 20:37:56 +080021import android.os.Binder;
22import android.os.RemoteException;
James.cf Lincad981c2019-12-10 20:37:56 +080023import android.os.ServiceSpecificException;
Brad Ebinger63b6f5a2020-10-27 11:43:35 -070024import android.os.UserHandle;
Brad Ebingerb7a866a2020-01-22 17:51:55 -080025import android.telephony.SubscriptionManager;
Peter Wangc035ce42020-01-08 21:00:22 -080026import android.telephony.TelephonyFrameworkInitializer;
Brad Ebingeraf1e9832020-10-14 10:49:28 -070027import android.telephony.ims.DelegateRequest;
James.cf Lincad981c2019-12-10 20:37:56 +080028import android.telephony.ims.ImsException;
James.cf Lin99a360d2020-11-04 10:48:37 +080029import android.telephony.ims.RcsUceAdapter.PublishState;
James.cf Lindc2d5422019-12-31 14:40:25 +080030import android.telephony.ims.RegistrationManager;
James.cf Linaf3183c2019-10-24 00:59:00 +080031import android.telephony.ims.aidl.IImsCapabilityCallback;
32import android.telephony.ims.aidl.IImsRcsController;
James.cf Lindc2d5422019-12-31 14:40:25 +080033import android.telephony.ims.aidl.IImsRegistrationCallback;
James.cf Linaf3183c2019-10-24 00:59:00 +080034import android.telephony.ims.aidl.IRcsUceControllerCallback;
James.cf Lincdad3862020-02-25 15:55:03 +080035import android.telephony.ims.aidl.IRcsUcePublishStateCallback;
Brad Ebingeraf1e9832020-10-14 10:49:28 -070036import android.telephony.ims.aidl.ISipDelegate;
37import android.telephony.ims.aidl.ISipDelegateConnectionStateCallback;
38import android.telephony.ims.aidl.ISipDelegateMessageCallback;
Brad Ebingere3ae65a2020-09-11 12:45:11 -070039import android.telephony.ims.feature.ImsFeature;
James.cf Linaf3183c2019-10-24 00:59:00 +080040import android.telephony.ims.feature.RcsFeature;
James.cf Lincad981c2019-12-10 20:37:56 +080041import android.telephony.ims.stub.ImsRegistrationImplBase;
James.cf Linaf3183c2019-10-24 00:59:00 +080042import android.util.Log;
43
James.cf Lindc2d5422019-12-31 14:40:25 +080044import com.android.ims.ImsManager;
Brad Ebingere3ae65a2020-09-11 12:45:11 -070045import com.android.ims.internal.IImsServiceFeatureCallback;
James.cf Lindc2d5422019-12-31 14:40:25 +080046import com.android.internal.telephony.IIntegerConsumer;
James.cf Lincad981c2019-12-10 20:37:56 +080047import com.android.internal.telephony.Phone;
Brad Ebinger8b79edc2020-02-27 19:13:24 -080048import com.android.internal.telephony.TelephonyPermissions;
Brad Ebingere3ae65a2020-09-11 12:45:11 -070049import com.android.internal.telephony.ims.ImsResolver;
James.cf Lincad981c2019-12-10 20:37:56 +080050import com.android.internal.telephony.imsphone.ImsPhone;
Brad Ebingera68a4972020-01-30 17:31:23 -080051import com.android.services.telephony.rcs.RcsFeatureController;
Brad Ebingerb989c7c2020-09-23 17:03:48 -070052import com.android.services.telephony.rcs.SipTransportController;
James.cf Linc9f35a42020-01-15 02:35:22 +080053import com.android.services.telephony.rcs.TelephonyRcsService;
James.cf Lin99a360d2020-11-04 10:48:37 +080054import com.android.services.telephony.rcs.UceControllerManager;
James.cf Lincad981c2019-12-10 20:37:56 +080055
James.cf Linaf3183c2019-10-24 00:59:00 +080056import java.util.List;
57
58/**
59 * Implementation of the IImsRcsController interface.
60 */
61public class ImsRcsController extends IImsRcsController.Stub {
62 private static final String TAG = "ImsRcsController";
63
64 /** The singleton instance. */
65 private static ImsRcsController sInstance;
66
67 private PhoneGlobals mApp;
James.cf Linc9f35a42020-01-15 02:35:22 +080068 private TelephonyRcsService mRcsService;
Brad Ebingere3ae65a2020-09-11 12:45:11 -070069 private ImsResolver mImsResolver;
Brad Ebinger49a72b42021-01-29 00:55:24 +000070 // set by shell cmd phone src set-device-enabled true/false
71 private Boolean mSingleRegistrationOverride;
James.cf Linaf3183c2019-10-24 00:59:00 +080072
73 /**
74 * Initialize the singleton ImsRcsController instance.
75 * This is only done once, at startup, from PhoneApp.onCreate().
76 */
77 static ImsRcsController init(PhoneGlobals app) {
78 synchronized (ImsRcsController.class) {
79 if (sInstance == null) {
80 sInstance = new ImsRcsController(app);
81 } else {
82 Log.wtf(TAG, "init() called multiple times! sInstance = " + sInstance);
83 }
84 return sInstance;
85 }
86 }
87
88 /** Private constructor; @see init() */
89 private ImsRcsController(PhoneGlobals app) {
90 Log.i(TAG, "ImsRcsController");
91 mApp = app;
Peter Wangc035ce42020-01-08 21:00:22 -080092 TelephonyFrameworkInitializer
93 .getTelephonyServiceManager().getTelephonyImsServiceRegisterer().register(this);
Brad Ebingere3ae65a2020-09-11 12:45:11 -070094 mImsResolver = mApp.getImsResolver();
James.cf Linaf3183c2019-10-24 00:59:00 +080095 }
96
James.cf Lincad981c2019-12-10 20:37:56 +080097 /**
Brad Ebingera68a4972020-01-30 17:31:23 -080098 * Register a {@link RegistrationManager.RegistrationCallback} to receive IMS network
99 * registration state.
James.cf Lindc2d5422019-12-31 14:40:25 +0800100 */
101 @Override
Brad Ebingera68a4972020-01-30 17:31:23 -0800102 public void registerImsRegistrationCallback(int subId, IImsRegistrationCallback callback) {
James.cf Linf020d162021-01-31 22:15:52 +0800103 TelephonyPermissions.enforeceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
104 mApp, subId, "registerImsRegistrationCallback");
James.cf Lindc2d5422019-12-31 14:40:25 +0800105 final long token = Binder.clearCallingIdentity();
106 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800107 getRcsFeatureController(subId).registerImsRegistrationCallback(subId, callback);
108 } catch (ImsException e) {
James.cf Lindc2d5422019-12-31 14:40:25 +0800109 Log.e(TAG, "registerImsRegistrationCallback: sudId=" + subId + ", " + e.getMessage());
110 throw new ServiceSpecificException(e.getCode());
111 } finally {
112 Binder.restoreCallingIdentity(token);
113 }
114 }
115
116 /**
Brad Ebingera68a4972020-01-30 17:31:23 -0800117 * Removes an existing {@link RegistrationManager.RegistrationCallback}.
James.cf Lindc2d5422019-12-31 14:40:25 +0800118 */
119 @Override
120 public void unregisterImsRegistrationCallback(int subId, IImsRegistrationCallback callback) {
James.cf Linf020d162021-01-31 22:15:52 +0800121 TelephonyPermissions.enforeceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
122 mApp, subId, "unregisterImsRegistrationCallback");
James.cf Lindc2d5422019-12-31 14:40:25 +0800123 final long token = Binder.clearCallingIdentity();
124 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800125 getRcsFeatureController(subId).unregisterImsRegistrationCallback(subId, callback);
James.cf Lindc2d5422019-12-31 14:40:25 +0800126 } catch (ServiceSpecificException e) {
127 Log.e(TAG, "unregisterImsRegistrationCallback: error=" + e.errorCode);
128 } finally {
129 Binder.restoreCallingIdentity(token);
130 }
131 }
132
133 /**
134 * Get the IMS service registration state for the RcsFeature associated with this sub id.
135 */
136 @Override
137 public void getImsRcsRegistrationState(int subId, IIntegerConsumer consumer) {
James.cf Linf020d162021-01-31 22:15:52 +0800138 TelephonyPermissions.enforeceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
139 mApp, subId, "getImsRcsRegistrationState");
James.cf Lindc2d5422019-12-31 14:40:25 +0800140 final long token = Binder.clearCallingIdentity();
141 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800142 getRcsFeatureController(subId).getRegistrationState(regState -> {
James.cf Lindc2d5422019-12-31 14:40:25 +0800143 try {
144 consumer.accept((regState == null)
145 ? RegistrationManager.REGISTRATION_STATE_NOT_REGISTERED : regState);
146 } catch (RemoteException e) {
147 Log.w(TAG, "getImsRcsRegistrationState: callback is not available.");
148 }
149 });
150 } finally {
151 Binder.restoreCallingIdentity(token);
152 }
153 }
154
155 /**
156 * Gets the Transport Type associated with the current IMS RCS registration.
157 */
158 @Override
159 public void getImsRcsRegistrationTransportType(int subId, IIntegerConsumer consumer) {
James.cf Linf020d162021-01-31 22:15:52 +0800160 TelephonyPermissions.enforeceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
161 mApp, subId, "getImsRcsRegistrationTransportType");
James.cf Lindc2d5422019-12-31 14:40:25 +0800162 final long token = Binder.clearCallingIdentity();
163 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800164 getRcsFeatureController(subId).getRegistrationTech(regTech -> {
James.cf Lindc2d5422019-12-31 14:40:25 +0800165 // Convert registration tech from ImsRegistrationImplBase -> RegistrationManager
166 int regTechConverted = (regTech == null)
167 ? ImsRegistrationImplBase.REGISTRATION_TECH_NONE : regTech;
168 regTechConverted = RegistrationManager.IMS_REG_TO_ACCESS_TYPE_MAP.get(
169 regTechConverted);
170 try {
171 consumer.accept(regTechConverted);
172 } catch (RemoteException e) {
173 Log.w(TAG, "getImsRcsRegistrationTransportType: callback is not available.");
174 }
175 });
176 } finally {
177 Binder.restoreCallingIdentity(token);
178 }
179 }
180
181 /**
James.cf Lincad981c2019-12-10 20:37:56 +0800182 * Register a capability callback which will provide RCS availability updates for the
183 * subscription specified.
184 *
185 * @param subId the subscription ID
186 * @param callback The ImsCapabilityCallback to be registered.
187 */
James.cf Linaf3183c2019-10-24 00:59:00 +0800188 @Override
Brad Ebingera68a4972020-01-30 17:31:23 -0800189 public void registerRcsAvailabilityCallback(int subId, IImsCapabilityCallback callback) {
James.cf Linaf3183c2019-10-24 00:59:00 +0800190 enforceReadPrivilegedPermission("registerRcsAvailabilityCallback");
James.cf Lincad981c2019-12-10 20:37:56 +0800191 final long token = Binder.clearCallingIdentity();
192 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800193 getRcsFeatureController(subId).registerRcsAvailabilityCallback(subId, callback);
194 } catch (ImsException e) {
James.cf Lincad981c2019-12-10 20:37:56 +0800195 Log.e(TAG, "registerRcsAvailabilityCallback: sudId=" + subId + ", " + e.getMessage());
196 throw new ServiceSpecificException(e.getCode());
197 } finally {
198 Binder.restoreCallingIdentity(token);
199 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800200 }
201
James.cf Lincad981c2019-12-10 20:37:56 +0800202 /**
203 * Remove the registered capability callback.
204 *
205 * @param subId the subscription ID
206 * @param callback The ImsCapabilityCallback to be removed.
207 */
James.cf Linaf3183c2019-10-24 00:59:00 +0800208 @Override
James.cf Lincad981c2019-12-10 20:37:56 +0800209 public void unregisterRcsAvailabilityCallback(int subId, IImsCapabilityCallback callback) {
James.cf Linaf3183c2019-10-24 00:59:00 +0800210 enforceReadPrivilegedPermission("unregisterRcsAvailabilityCallback");
James.cf Lincad981c2019-12-10 20:37:56 +0800211 final long token = Binder.clearCallingIdentity();
212 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800213 getRcsFeatureController(subId).unregisterRcsAvailabilityCallback(subId, callback);
James.cf Lincad981c2019-12-10 20:37:56 +0800214 } finally {
215 Binder.restoreCallingIdentity(token);
216 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800217 }
218
James.cf Lincad981c2019-12-10 20:37:56 +0800219 /**
220 * Query for the capability of an IMS RCS service
221 *
222 * @param subId the subscription ID
223 * @param capability the RCS capability to query.
James.cf Linf020d162021-01-31 22:15:52 +0800224 * @param radioTech the radio technology type that we are querying.
James.cf Lincad981c2019-12-10 20:37:56 +0800225 * @return true if the RCS capability is capable for this subscription, false otherwise.
226 */
James.cf Linaf3183c2019-10-24 00:59:00 +0800227 @Override
228 public boolean isCapable(int subId,
James.cf Lincad981c2019-12-10 20:37:56 +0800229 @RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability,
230 @ImsRegistrationImplBase.ImsRegistrationTech int radioTech) {
James.cf Linaf3183c2019-10-24 00:59:00 +0800231 enforceReadPrivilegedPermission("isCapable");
James.cf Lincad981c2019-12-10 20:37:56 +0800232 final long token = Binder.clearCallingIdentity();
233 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800234 return getRcsFeatureController(subId).isCapable(capability, radioTech);
235 } catch (ImsException e) {
James.cf Lincad981c2019-12-10 20:37:56 +0800236 Log.e(TAG, "isCapable: sudId=" + subId
237 + ", capability=" + capability + ", " + e.getMessage());
238 return false;
239 } finally {
240 Binder.restoreCallingIdentity(token);
241 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800242 }
243
James.cf Lincad981c2019-12-10 20:37:56 +0800244 /**
245 * Query the availability of an IMS RCS capability.
246 *
247 * @param subId the subscription ID
248 * @param capability the RCS capability to query.
249 * @return true if the RCS capability is currently available for the associated subscription,
James.cf Linf020d162021-01-31 22:15:52 +0800250 * @param radioTech the radio technology type that we are querying.
James.cf Lincad981c2019-12-10 20:37:56 +0800251 * false otherwise.
252 */
James.cf Linaf3183c2019-10-24 00:59:00 +0800253 @Override
254 public boolean isAvailable(int subId,
James.cf Linf020d162021-01-31 22:15:52 +0800255 @RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability,
256 @ImsRegistrationImplBase.ImsRegistrationTech int radioTech) {
James.cf Linaf3183c2019-10-24 00:59:00 +0800257 enforceReadPrivilegedPermission("isAvailable");
James.cf Lincad981c2019-12-10 20:37:56 +0800258 final long token = Binder.clearCallingIdentity();
259 try {
James.cf Linf020d162021-01-31 22:15:52 +0800260 return getRcsFeatureController(subId).isAvailable(capability, radioTech);
Brad Ebingera68a4972020-01-30 17:31:23 -0800261 } catch (ImsException e) {
James.cf Lincad981c2019-12-10 20:37:56 +0800262 Log.e(TAG, "isAvailable: sudId=" + subId
263 + ", capability=" + capability + ", " + e.getMessage());
264 return false;
265 } finally {
266 Binder.restoreCallingIdentity(token);
267 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800268 }
269
270 @Override
Brad Ebinger8b79edc2020-02-27 19:13:24 -0800271 public void requestCapabilities(int subId, String callingPackage, String callingFeatureId,
272 List<Uri> contactNumbers, IRcsUceControllerCallback c) {
James.cf Linaf3183c2019-10-24 00:59:00 +0800273 enforceReadPrivilegedPermission("requestCapabilities");
Brad Ebingera68a4972020-01-30 17:31:23 -0800274 final long token = Binder.clearCallingIdentity();
275 try {
James.cf Lin99a360d2020-11-04 10:48:37 +0800276 UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
277 UceControllerManager.class);
278 if (uceCtrlManager == null) {
Brad Ebingera68a4972020-01-30 17:31:23 -0800279 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
280 "This subscription does not support UCE.");
281 }
James.cf Lin99a360d2020-11-04 10:48:37 +0800282 uceCtrlManager.requestCapabilities(contactNumbers, c);
283 } catch (ImsException e) {
284 throw new ServiceSpecificException(e.getCode(), e.getMessage());
Brad Ebingera68a4972020-01-30 17:31:23 -0800285 } finally {
286 Binder.restoreCallingIdentity(token);
Brad Ebinger1aa94992020-01-22 14:17:23 -0800287 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800288 }
289
290 @Override
James.cf Linbcdf8b32021-01-14 16:44:13 +0800291 public void requestAvailability(int subId, String callingPackage,
James.cf Lin64e91212020-10-30 01:09:52 +0800292 String callingFeatureId, Uri contactNumber, IRcsUceControllerCallback c) {
James.cf Linbcdf8b32021-01-14 16:44:13 +0800293 enforceReadPrivilegedPermission("requestAvailability");
Brad Ebingera68a4972020-01-30 17:31:23 -0800294 final long token = Binder.clearCallingIdentity();
295 try {
James.cf Lin99a360d2020-11-04 10:48:37 +0800296 UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
297 UceControllerManager.class);
298 if (uceCtrlManager == null) {
Brad Ebingera68a4972020-01-30 17:31:23 -0800299 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
300 "This subscription does not support UCE.");
301 }
James.cf Lin99a360d2020-11-04 10:48:37 +0800302 uceCtrlManager.requestNetworkAvailability(contactNumber, c);
303 } catch (ImsException e) {
304 throw new ServiceSpecificException(e.getCode(), e.getMessage());
305 } finally {
306 Binder.restoreCallingIdentity(token);
307 }
308 }
309
310 @Override
311 public @PublishState int getUcePublishState(int subId) {
312 enforceReadPrivilegedPermission("getUcePublishState");
313 final long token = Binder.clearCallingIdentity();
314 try {
315 UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
316 UceControllerManager.class);
317 if (uceCtrlManager == null) {
318 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
319 "This subscription does not support UCE.");
320 }
321 return uceCtrlManager.getUcePublishState();
322 } catch (ImsException e) {
323 throw new ServiceSpecificException(e.getCode(), e.getMessage());
324 } finally {
325 Binder.restoreCallingIdentity(token);
326 }
327 }
328
329 @Override
330 public void registerUcePublishStateCallback(int subId, IRcsUcePublishStateCallback c) {
331 enforceReadPrivilegedPermission("registerUcePublishStateCallback");
332 final long token = Binder.clearCallingIdentity();
333 try {
334 UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
335 UceControllerManager.class);
336 if (uceCtrlManager == null) {
337 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
338 "This subscription does not support UCE.");
339 }
340 uceCtrlManager.registerPublishStateCallback(c);
341 } catch (ImsException e) {
342 throw new ServiceSpecificException(e.getCode(), e.getMessage());
343 } finally {
344 Binder.restoreCallingIdentity(token);
345 }
346 }
347
348 @Override
349 public void unregisterUcePublishStateCallback(int subId, IRcsUcePublishStateCallback c) {
350 enforceReadPrivilegedPermission("unregisterUcePublishStateCallback");
351 final long token = Binder.clearCallingIdentity();
352 try {
353 UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
354 UceControllerManager.class);
355 if (uceCtrlManager == null) {
356 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
357 "This subscription does not support UCE.");
358 }
359 uceCtrlManager.unregisterPublishStateCallback(c);
Brad Ebingera68a4972020-01-30 17:31:23 -0800360 } finally {
361 Binder.restoreCallingIdentity(token);
Brad Ebinger1aa94992020-01-22 14:17:23 -0800362 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800363 }
364
365 @Override
Brad Ebinger8b79edc2020-02-27 19:13:24 -0800366 public boolean isUceSettingEnabled(int subId, String callingPackage, String callingFeatureId) {
367 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
368 mApp, subId, callingPackage, callingFeatureId, "isUceSettingEnabled")) {
369 Log.w(TAG, "isUceSettingEnabled: READ_PHONE_STATE app op disabled when accessing "
370 + "isUceSettingEnabled");
371 return false;
372 }
373 final long token = Binder.clearCallingIdentity();
374 try {
375 return SubscriptionManager.getBooleanSubscriptionProperty(subId,
376 SubscriptionManager.IMS_RCS_UCE_ENABLED, false /*defaultValue*/, mApp);
377 } finally {
378 Binder.restoreCallingIdentity(token);
379 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800380 }
381
382 @Override
383 public void setUceSettingEnabled(int subId, boolean isEnabled) {
384 enforceModifyPermission();
Brad Ebinger8b79edc2020-02-27 19:13:24 -0800385 final long token = Binder.clearCallingIdentity();
386 try {
387 SubscriptionManager.setSubscriptionProperty(subId,
388 SubscriptionManager.IMS_RCS_UCE_ENABLED, (isEnabled ? "1" : "0"));
389 } finally {
390 Binder.restoreCallingIdentity(token);
391 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800392 }
393
Brad Ebingerb989c7c2020-09-23 17:03:48 -0700394 @Override
395 public boolean isSipDelegateSupported(int subId) {
396 enforceReadPrivilegedPermission("isSipDelegateSupported");
Brad Ebinger49a72b42021-01-29 00:55:24 +0000397 if (!isImsSingleRegistrationSupportedOnDevice()) {
398 return false;
399 }
Brad Ebingerb989c7c2020-09-23 17:03:48 -0700400 final long token = Binder.clearCallingIdentity();
401 try {
402 SipTransportController transport = getRcsFeatureController(subId).getFeature(
403 SipTransportController.class);
404 if (transport == null) {
405 return false;
406 }
407 return transport.isSupported(subId);
408 } catch (ImsException e) {
409 throw new ServiceSpecificException(e.getCode(), e.getMessage());
410 } catch (ServiceSpecificException e) {
411 if (e.errorCode == ImsException.CODE_ERROR_UNSUPPORTED_OPERATION) {
412 return false;
413 }
414 throw e;
415 } finally {
416 Binder.restoreCallingIdentity(token);
417 }
418 }
419
Brad Ebingeraf1e9832020-10-14 10:49:28 -0700420 @Override
Brad Ebinger63b6f5a2020-10-27 11:43:35 -0700421 public void createSipDelegate(int subId, DelegateRequest request, String packageName,
Brad Ebingeraf1e9832020-10-14 10:49:28 -0700422 ISipDelegateConnectionStateCallback delegateState,
423 ISipDelegateMessageCallback delegateMessage) {
424 enforceModifyPermission();
Brad Ebinger49a72b42021-01-29 00:55:24 +0000425 if (!isImsSingleRegistrationSupportedOnDevice()) {
426 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
427 "SipDelegate creation is only supported for devices supporting IMS single "
428 + "registration");
429 }
Brad Ebinger63b6f5a2020-10-27 11:43:35 -0700430 if (!UserHandle.getUserHandleForUid(Binder.getCallingUid()).isSystem()) {
431 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
432 "SipDelegate creation is only available to primary user.");
433 }
434 try {
435 int remoteUid = mApp.getPackageManager().getPackageUid(packageName, 0 /*flags*/);
436 if (Binder.getCallingUid() != remoteUid) {
437 throw new SecurityException("passed in packageName does not match the caller");
438 }
439 } catch (PackageManager.NameNotFoundException e) {
440 throw new SecurityException("Passed in PackageName can not be found on device");
441 }
Brad Ebingeraf1e9832020-10-14 10:49:28 -0700442
443 final long identity = Binder.clearCallingIdentity();
444 SipTransportController transport = getRcsFeatureController(subId).getFeature(
445 SipTransportController.class);
446 if (transport == null) {
447 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
448 "This subscription does not support the creation of SIP delegates");
449 }
450 try {
Brad Ebinger63b6f5a2020-10-27 11:43:35 -0700451 transport.createSipDelegate(subId, request, packageName, delegateState,
452 delegateMessage);
Brad Ebingeraf1e9832020-10-14 10:49:28 -0700453 } catch (ImsException e) {
454 throw new ServiceSpecificException(e.getCode(), e.getMessage());
455 } finally {
456 Binder.restoreCallingIdentity(identity);
457 }
458 }
459
460 @Override
461 public void destroySipDelegate(int subId, ISipDelegate connection, int reason) {
462 enforceModifyPermission();
463
464 final long identity = Binder.clearCallingIdentity();
465 try {
Brad Ebinger63b6f5a2020-10-27 11:43:35 -0700466 SipTransportController transport = getRcsFeatureController(subId).getFeature(
467 SipTransportController.class);
468 if (transport == null) {
469 return;
470 }
471 transport.destroySipDelegate(subId, connection, reason);
Brad Ebingeraf1e9832020-10-14 10:49:28 -0700472 } finally {
473 Binder.restoreCallingIdentity(identity);
474 }
475 }
476
Brad Ebinger36221382020-12-09 00:33:39 +0000477 @Override
478 public void triggerNetworkRegistration(int subId, ISipDelegate connection, int sipCode,
479 String sipReason) {
480 enforceModifyPermission();
481
482 final long identity = Binder.clearCallingIdentity();
483 try {
484 SipTransportController transport = getRcsFeatureController(subId).getFeature(
485 SipTransportController.class);
486 if (transport == null) {
487 return;
488 }
489 transport.triggerFullNetworkRegistration(subId, connection, sipCode, sipReason);
490 } finally {
491 Binder.restoreCallingIdentity(identity);
492 }
493 }
494
James.cf Linaf3183c2019-10-24 00:59:00 +0800495 /**
Brad Ebingere3ae65a2020-09-11 12:45:11 -0700496 * Registers for updates to the RcsFeature connection through the IImsServiceFeatureCallback
497 * callback.
498 */
499 @Override
Brad Ebinger6366ce92020-10-01 13:51:05 -0700500 public void registerRcsFeatureCallback(int slotId, IImsServiceFeatureCallback callback) {
Brad Ebingere3ae65a2020-09-11 12:45:11 -0700501 enforceModifyPermission();
502
503 final long identity = Binder.clearCallingIdentity();
504 try {
505 if (mImsResolver == null) {
506 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
507 "Device does not support IMS");
508 }
Brad Ebinger6366ce92020-10-01 13:51:05 -0700509 mImsResolver.listenForFeature(slotId, ImsFeature.FEATURE_RCS, callback);
Brad Ebingere3ae65a2020-09-11 12:45:11 -0700510 } finally {
511 Binder.restoreCallingIdentity(identity);
512 }
513 }
Brad Ebinger6366ce92020-10-01 13:51:05 -0700514
Brad Ebingere3ae65a2020-09-11 12:45:11 -0700515 /**
516 * Unregister a previously registered IImsServiceFeatureCallback associated with an ImsFeature.
517 */
518 @Override
519 public void unregisterImsFeatureCallback(IImsServiceFeatureCallback callback) {
520 enforceModifyPermission();
521
522 final long identity = Binder.clearCallingIdentity();
523 try {
524 if (mImsResolver == null) return;
525 mImsResolver.unregisterImsFeatureCallback(callback);
526 } finally {
527 Binder.restoreCallingIdentity(identity);
528 }
529 }
530
531 /**
James.cf Linaf3183c2019-10-24 00:59:00 +0800532 * Make sure either called from same process as self (phone) or IPC caller has read privilege.
533 *
534 * @throws SecurityException if the caller does not have the required permission
535 */
536 private void enforceReadPrivilegedPermission(String message) {
537 mApp.enforceCallingOrSelfPermission(
538 android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, message);
539 }
540
541 /**
542 * Make sure the caller has the MODIFY_PHONE_STATE permission.
543 *
544 * @throws SecurityException if the caller does not have the required permission
545 */
546 private void enforceModifyPermission() {
547 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE, null);
548 }
James.cf Lincad981c2019-12-10 20:37:56 +0800549
550 /**
James.cf Lindc2d5422019-12-31 14:40:25 +0800551 * Retrieve ImsPhone instance.
James.cf Lincad981c2019-12-10 20:37:56 +0800552 *
553 * @param subId the subscription ID
James.cf Lindc2d5422019-12-31 14:40:25 +0800554 * @return The ImsPhone instance
555 * @throws ServiceSpecificException if getting ImsPhone instance failed.
James.cf Lincad981c2019-12-10 20:37:56 +0800556 */
James.cf Lindc2d5422019-12-31 14:40:25 +0800557 private ImsPhone getImsPhone(int subId) {
558 if (!ImsManager.isImsSupportedOnDevice(mApp)) {
559 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
560 "IMS is not available on device.");
561 }
James.cf Lincad981c2019-12-10 20:37:56 +0800562 Phone phone = PhoneGlobals.getPhone(subId);
563 if (phone == null) {
564 throw new ServiceSpecificException(ImsException.CODE_ERROR_INVALID_SUBSCRIPTION,
565 "Invalid subscription Id: " + subId);
566 }
567 ImsPhone imsPhone = (ImsPhone) phone.getImsPhone();
568 if (imsPhone == null) {
James.cf Lindc2d5422019-12-31 14:40:25 +0800569 throw new ServiceSpecificException(ImsException.CODE_ERROR_SERVICE_UNAVAILABLE,
570 "Cannot find ImsPhone instance: " + subId);
571 }
572 return imsPhone;
573 }
574
575 /**
576 * Retrieve RcsFeatureManager instance.
577 *
578 * @param subId the subscription ID
579 * @return The RcsFeatureManager instance
580 * @throws ServiceSpecificException if getting RcsFeatureManager instance failed.
581 */
Brad Ebingera68a4972020-01-30 17:31:23 -0800582 private RcsFeatureController getRcsFeatureController(int subId) {
James.cf Lindc2d5422019-12-31 14:40:25 +0800583 if (!ImsManager.isImsSupportedOnDevice(mApp)) {
James.cf Lincad981c2019-12-10 20:37:56 +0800584 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
James.cf Lindc2d5422019-12-31 14:40:25 +0800585 "IMS is not available on device.");
586 }
Brad Ebingera68a4972020-01-30 17:31:23 -0800587 if (mRcsService == null) {
588 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
589 "IMS is not available on device.");
590 }
James.cf Lindc2d5422019-12-31 14:40:25 +0800591 Phone phone = PhoneGlobals.getPhone(subId);
592 if (phone == null) {
593 throw new ServiceSpecificException(ImsException.CODE_ERROR_INVALID_SUBSCRIPTION,
594 "Invalid subscription Id: " + subId);
595 }
Brad Ebingera68a4972020-01-30 17:31:23 -0800596 int slotId = phone.getPhoneId();
597 RcsFeatureController c = mRcsService.getFeatureController(slotId);
598 if (c == null) {
Brad Ebinger036dc9e2020-02-06 15:49:06 -0800599 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
600 "The requested operation is not supported for subId " + subId);
James.cf Lincad981c2019-12-10 20:37:56 +0800601 }
Brad Ebingera68a4972020-01-30 17:31:23 -0800602 return c;
James.cf Lincad981c2019-12-10 20:37:56 +0800603 }
James.cf Linc9f35a42020-01-15 02:35:22 +0800604
Brad Ebinger49a72b42021-01-29 00:55:24 +0000605 private boolean isImsSingleRegistrationSupportedOnDevice() {
606 return mSingleRegistrationOverride != null ? mSingleRegistrationOverride
607 : mApp.getPackageManager().hasSystemFeature(
608 PackageManager.FEATURE_TELEPHONY_IMS_SINGLE_REGISTRATION);
609 }
610
James.cf Linc9f35a42020-01-15 02:35:22 +0800611 void setRcsService(TelephonyRcsService rcsService) {
612 mRcsService = rcsService;
613 }
Brad Ebinger49a72b42021-01-29 00:55:24 +0000614
615 /**
616 * Override device RCS single registration support check for CTS testing or remove override
617 * if the Boolean is set to null.
618 */
619 void setDeviceSingleRegistrationSupportOverride(Boolean deviceOverrideValue) {
620 mSingleRegistrationOverride = deviceOverrideValue;
621 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800622}