blob: 2e4ee94d4885a2aaf53ac3c2da9d5e2d1d7f89c5 [file] [log] [blame]
James.cf Linaf3183c2019-10-24 00:59:00 +08001/*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.phone;
18
Brad Ebinger4df7e242021-02-17 23:23:21 +000019import android.Manifest;
Brad Ebinger63b6f5a2020-10-27 11:43:35 -070020import android.content.pm.PackageManager;
James.cf Linaf3183c2019-10-24 00:59:00 +080021import android.net.Uri;
James.cf Lincad981c2019-12-10 20:37:56 +080022import android.os.Binder;
23import android.os.RemoteException;
James.cf Lincad981c2019-12-10 20:37:56 +080024import android.os.ServiceSpecificException;
Brad Ebinger63b6f5a2020-10-27 11:43:35 -070025import android.os.UserHandle;
Brad Ebingerb7a866a2020-01-22 17:51:55 -080026import android.telephony.SubscriptionManager;
Peter Wangc035ce42020-01-08 21:00:22 -080027import android.telephony.TelephonyFrameworkInitializer;
Brad Ebingeraf1e9832020-10-14 10:49:28 -070028import android.telephony.ims.DelegateRequest;
James.cf Lincad981c2019-12-10 20:37:56 +080029import android.telephony.ims.ImsException;
Brad Ebingerd4c5bde2021-02-12 06:18:28 +000030import android.telephony.ims.RcsContactUceCapability;
James.cf Lin99a360d2020-11-04 10:48:37 +080031import android.telephony.ims.RcsUceAdapter.PublishState;
James.cf Lindc2d5422019-12-31 14:40:25 +080032import android.telephony.ims.RegistrationManager;
James.cf Linaf3183c2019-10-24 00:59:00 +080033import android.telephony.ims.aidl.IImsCapabilityCallback;
34import android.telephony.ims.aidl.IImsRcsController;
James.cf Lindc2d5422019-12-31 14:40:25 +080035import android.telephony.ims.aidl.IImsRegistrationCallback;
James.cf Linaf3183c2019-10-24 00:59:00 +080036import android.telephony.ims.aidl.IRcsUceControllerCallback;
James.cf Lincdad3862020-02-25 15:55:03 +080037import android.telephony.ims.aidl.IRcsUcePublishStateCallback;
Brad Ebingeraf1e9832020-10-14 10:49:28 -070038import android.telephony.ims.aidl.ISipDelegate;
39import android.telephony.ims.aidl.ISipDelegateConnectionStateCallback;
40import android.telephony.ims.aidl.ISipDelegateMessageCallback;
Brad Ebingere3ae65a2020-09-11 12:45:11 -070041import android.telephony.ims.feature.ImsFeature;
James.cf Linaf3183c2019-10-24 00:59:00 +080042import android.telephony.ims.feature.RcsFeature;
James.cf Lincad981c2019-12-10 20:37:56 +080043import android.telephony.ims.stub.ImsRegistrationImplBase;
James.cf Linaf3183c2019-10-24 00:59:00 +080044import android.util.Log;
45
James.cf Lindc2d5422019-12-31 14:40:25 +080046import com.android.ims.ImsManager;
Brad Ebingere3ae65a2020-09-11 12:45:11 -070047import com.android.ims.internal.IImsServiceFeatureCallback;
James.cf Lindc2d5422019-12-31 14:40:25 +080048import com.android.internal.telephony.IIntegerConsumer;
James.cf Lincad981c2019-12-10 20:37:56 +080049import com.android.internal.telephony.Phone;
Brad Ebinger8b79edc2020-02-27 19:13:24 -080050import com.android.internal.telephony.TelephonyPermissions;
Brad Ebingere3ae65a2020-09-11 12:45:11 -070051import com.android.internal.telephony.ims.ImsResolver;
James.cf Lincad981c2019-12-10 20:37:56 +080052import com.android.internal.telephony.imsphone.ImsPhone;
Brad Ebingera68a4972020-01-30 17:31:23 -080053import com.android.services.telephony.rcs.RcsFeatureController;
Brad Ebingerb989c7c2020-09-23 17:03:48 -070054import com.android.services.telephony.rcs.SipTransportController;
James.cf Linc9f35a42020-01-15 02:35:22 +080055import com.android.services.telephony.rcs.TelephonyRcsService;
James.cf Lin99a360d2020-11-04 10:48:37 +080056import com.android.services.telephony.rcs.UceControllerManager;
James.cf Lincad981c2019-12-10 20:37:56 +080057
James.cf Linaf3183c2019-10-24 00:59:00 +080058import java.util.List;
Brad Ebingerd4c5bde2021-02-12 06:18:28 +000059import java.util.Set;
James.cf Linaf3183c2019-10-24 00:59:00 +080060
61/**
62 * Implementation of the IImsRcsController interface.
63 */
64public class ImsRcsController extends IImsRcsController.Stub {
65 private static final String TAG = "ImsRcsController";
66
67 /** The singleton instance. */
68 private static ImsRcsController sInstance;
69
70 private PhoneGlobals mApp;
James.cf Linc9f35a42020-01-15 02:35:22 +080071 private TelephonyRcsService mRcsService;
Brad Ebingere3ae65a2020-09-11 12:45:11 -070072 private ImsResolver mImsResolver;
Brad Ebinger49a72b42021-01-29 00:55:24 +000073 // set by shell cmd phone src set-device-enabled true/false
74 private Boolean mSingleRegistrationOverride;
James.cf Linaf3183c2019-10-24 00:59:00 +080075
76 /**
77 * Initialize the singleton ImsRcsController instance.
78 * This is only done once, at startup, from PhoneApp.onCreate().
79 */
80 static ImsRcsController init(PhoneGlobals app) {
81 synchronized (ImsRcsController.class) {
82 if (sInstance == null) {
83 sInstance = new ImsRcsController(app);
84 } else {
85 Log.wtf(TAG, "init() called multiple times! sInstance = " + sInstance);
86 }
87 return sInstance;
88 }
89 }
90
91 /** Private constructor; @see init() */
92 private ImsRcsController(PhoneGlobals app) {
93 Log.i(TAG, "ImsRcsController");
94 mApp = app;
Peter Wangc035ce42020-01-08 21:00:22 -080095 TelephonyFrameworkInitializer
96 .getTelephonyServiceManager().getTelephonyImsServiceRegisterer().register(this);
Brad Ebingerd1947d82021-05-17 20:54:49 +000097 mImsResolver = ImsResolver.getInstance();
James.cf Linaf3183c2019-10-24 00:59:00 +080098 }
99
James.cf Lincad981c2019-12-10 20:37:56 +0800100 /**
Brad Ebingera68a4972020-01-30 17:31:23 -0800101 * Register a {@link RegistrationManager.RegistrationCallback} to receive IMS network
102 * registration state.
James.cf Lindc2d5422019-12-31 14:40:25 +0800103 */
104 @Override
Brad Ebingera68a4972020-01-30 17:31:23 -0800105 public void registerImsRegistrationCallback(int subId, IImsRegistrationCallback callback) {
Nathan Harold75a9ff12021-04-06 11:26:02 -0700106 TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
James.cf Linf020d162021-01-31 22:15:52 +0800107 mApp, subId, "registerImsRegistrationCallback");
James.cf Lindc2d5422019-12-31 14:40:25 +0800108 final long token = Binder.clearCallingIdentity();
109 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800110 getRcsFeatureController(subId).registerImsRegistrationCallback(subId, callback);
111 } catch (ImsException e) {
James.cf Lindc2d5422019-12-31 14:40:25 +0800112 Log.e(TAG, "registerImsRegistrationCallback: sudId=" + subId + ", " + e.getMessage());
113 throw new ServiceSpecificException(e.getCode());
114 } finally {
115 Binder.restoreCallingIdentity(token);
116 }
117 }
118
119 /**
Brad Ebingera68a4972020-01-30 17:31:23 -0800120 * Removes an existing {@link RegistrationManager.RegistrationCallback}.
James.cf Lindc2d5422019-12-31 14:40:25 +0800121 */
122 @Override
123 public void unregisterImsRegistrationCallback(int subId, IImsRegistrationCallback callback) {
Nathan Harold75a9ff12021-04-06 11:26:02 -0700124 TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
James.cf Linf020d162021-01-31 22:15:52 +0800125 mApp, subId, "unregisterImsRegistrationCallback");
James.cf Lindc2d5422019-12-31 14:40:25 +0800126 final long token = Binder.clearCallingIdentity();
127 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800128 getRcsFeatureController(subId).unregisterImsRegistrationCallback(subId, callback);
James.cf Lindc2d5422019-12-31 14:40:25 +0800129 } catch (ServiceSpecificException e) {
130 Log.e(TAG, "unregisterImsRegistrationCallback: error=" + e.errorCode);
131 } finally {
132 Binder.restoreCallingIdentity(token);
133 }
134 }
135
136 /**
137 * Get the IMS service registration state for the RcsFeature associated with this sub id.
138 */
139 @Override
140 public void getImsRcsRegistrationState(int subId, IIntegerConsumer consumer) {
Nathan Harold75a9ff12021-04-06 11:26:02 -0700141 TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
James.cf Linf020d162021-01-31 22:15:52 +0800142 mApp, subId, "getImsRcsRegistrationState");
James.cf Lindc2d5422019-12-31 14:40:25 +0800143 final long token = Binder.clearCallingIdentity();
144 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800145 getRcsFeatureController(subId).getRegistrationState(regState -> {
James.cf Lindc2d5422019-12-31 14:40:25 +0800146 try {
147 consumer.accept((regState == null)
148 ? RegistrationManager.REGISTRATION_STATE_NOT_REGISTERED : regState);
149 } catch (RemoteException e) {
150 Log.w(TAG, "getImsRcsRegistrationState: callback is not available.");
151 }
152 });
153 } finally {
154 Binder.restoreCallingIdentity(token);
155 }
156 }
157
158 /**
159 * Gets the Transport Type associated with the current IMS RCS registration.
160 */
161 @Override
162 public void getImsRcsRegistrationTransportType(int subId, IIntegerConsumer consumer) {
Nathan Harold75a9ff12021-04-06 11:26:02 -0700163 TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
James.cf Linf020d162021-01-31 22:15:52 +0800164 mApp, subId, "getImsRcsRegistrationTransportType");
James.cf Lindc2d5422019-12-31 14:40:25 +0800165 final long token = Binder.clearCallingIdentity();
166 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800167 getRcsFeatureController(subId).getRegistrationTech(regTech -> {
James.cf Lindc2d5422019-12-31 14:40:25 +0800168 // Convert registration tech from ImsRegistrationImplBase -> RegistrationManager
169 int regTechConverted = (regTech == null)
170 ? ImsRegistrationImplBase.REGISTRATION_TECH_NONE : regTech;
171 regTechConverted = RegistrationManager.IMS_REG_TO_ACCESS_TYPE_MAP.get(
172 regTechConverted);
173 try {
174 consumer.accept(regTechConverted);
175 } catch (RemoteException e) {
176 Log.w(TAG, "getImsRcsRegistrationTransportType: callback is not available.");
177 }
178 });
179 } finally {
180 Binder.restoreCallingIdentity(token);
181 }
182 }
183
184 /**
James.cf Lincad981c2019-12-10 20:37:56 +0800185 * Register a capability callback which will provide RCS availability updates for the
186 * subscription specified.
187 *
188 * @param subId the subscription ID
189 * @param callback The ImsCapabilityCallback to be registered.
190 */
James.cf Linaf3183c2019-10-24 00:59:00 +0800191 @Override
Brad Ebingera68a4972020-01-30 17:31:23 -0800192 public void registerRcsAvailabilityCallback(int subId, IImsCapabilityCallback callback) {
James.cf Linaf3183c2019-10-24 00:59:00 +0800193 enforceReadPrivilegedPermission("registerRcsAvailabilityCallback");
James.cf Lincad981c2019-12-10 20:37:56 +0800194 final long token = Binder.clearCallingIdentity();
195 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800196 getRcsFeatureController(subId).registerRcsAvailabilityCallback(subId, callback);
197 } catch (ImsException e) {
James.cf Lincad981c2019-12-10 20:37:56 +0800198 Log.e(TAG, "registerRcsAvailabilityCallback: sudId=" + subId + ", " + e.getMessage());
199 throw new ServiceSpecificException(e.getCode());
200 } finally {
201 Binder.restoreCallingIdentity(token);
202 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800203 }
204
James.cf Lincad981c2019-12-10 20:37:56 +0800205 /**
206 * Remove the registered capability callback.
207 *
208 * @param subId the subscription ID
209 * @param callback The ImsCapabilityCallback to be removed.
210 */
James.cf Linaf3183c2019-10-24 00:59:00 +0800211 @Override
James.cf Lincad981c2019-12-10 20:37:56 +0800212 public void unregisterRcsAvailabilityCallback(int subId, IImsCapabilityCallback callback) {
James.cf Linaf3183c2019-10-24 00:59:00 +0800213 enforceReadPrivilegedPermission("unregisterRcsAvailabilityCallback");
James.cf Lincad981c2019-12-10 20:37:56 +0800214 final long token = Binder.clearCallingIdentity();
215 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800216 getRcsFeatureController(subId).unregisterRcsAvailabilityCallback(subId, callback);
James.cf Lincad981c2019-12-10 20:37:56 +0800217 } finally {
218 Binder.restoreCallingIdentity(token);
219 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800220 }
221
James.cf Lincad981c2019-12-10 20:37:56 +0800222 /**
223 * Query for the capability of an IMS RCS service
224 *
225 * @param subId the subscription ID
226 * @param capability the RCS capability to query.
James.cf Linf020d162021-01-31 22:15:52 +0800227 * @param radioTech the radio technology type that we are querying.
James.cf Lincad981c2019-12-10 20:37:56 +0800228 * @return true if the RCS capability is capable for this subscription, false otherwise.
229 */
James.cf Linaf3183c2019-10-24 00:59:00 +0800230 @Override
231 public boolean isCapable(int subId,
James.cf Lincad981c2019-12-10 20:37:56 +0800232 @RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability,
233 @ImsRegistrationImplBase.ImsRegistrationTech int radioTech) {
James.cf Linaf3183c2019-10-24 00:59:00 +0800234 enforceReadPrivilegedPermission("isCapable");
James.cf Lincad981c2019-12-10 20:37:56 +0800235 final long token = Binder.clearCallingIdentity();
236 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800237 return getRcsFeatureController(subId).isCapable(capability, radioTech);
238 } catch (ImsException e) {
James.cf Lincad981c2019-12-10 20:37:56 +0800239 Log.e(TAG, "isCapable: sudId=" + subId
240 + ", capability=" + capability + ", " + e.getMessage());
241 return false;
242 } finally {
243 Binder.restoreCallingIdentity(token);
244 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800245 }
246
James.cf Lincad981c2019-12-10 20:37:56 +0800247 /**
248 * Query the availability of an IMS RCS capability.
249 *
250 * @param subId the subscription ID
251 * @param capability the RCS capability to query.
252 * @return true if the RCS capability is currently available for the associated subscription,
James.cf Linf020d162021-01-31 22:15:52 +0800253 * @param radioTech the radio technology type that we are querying.
James.cf Lincad981c2019-12-10 20:37:56 +0800254 * false otherwise.
255 */
James.cf Linaf3183c2019-10-24 00:59:00 +0800256 @Override
257 public boolean isAvailable(int subId,
James.cf Linf020d162021-01-31 22:15:52 +0800258 @RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability,
259 @ImsRegistrationImplBase.ImsRegistrationTech int radioTech) {
James.cf Linaf3183c2019-10-24 00:59:00 +0800260 enforceReadPrivilegedPermission("isAvailable");
James.cf Lincad981c2019-12-10 20:37:56 +0800261 final long token = Binder.clearCallingIdentity();
262 try {
James.cf Linf020d162021-01-31 22:15:52 +0800263 return getRcsFeatureController(subId).isAvailable(capability, radioTech);
Brad Ebingera68a4972020-01-30 17:31:23 -0800264 } catch (ImsException e) {
James.cf Lincad981c2019-12-10 20:37:56 +0800265 Log.e(TAG, "isAvailable: sudId=" + subId
266 + ", capability=" + capability + ", " + e.getMessage());
267 return false;
268 } finally {
269 Binder.restoreCallingIdentity(token);
270 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800271 }
272
273 @Override
Brad Ebinger8b79edc2020-02-27 19:13:24 -0800274 public void requestCapabilities(int subId, String callingPackage, String callingFeatureId,
275 List<Uri> contactNumbers, IRcsUceControllerCallback c) {
James.cf Lin051dd252021-01-21 03:30:54 +0800276 enforceAccessUserCapabilityExchangePermission("requestCapabilities");
277 enforceReadContactsPermission("requestCapabilities");
Brad Ebingera68a4972020-01-30 17:31:23 -0800278 final long token = Binder.clearCallingIdentity();
279 try {
James.cf Lin99a360d2020-11-04 10:48:37 +0800280 UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
281 UceControllerManager.class);
282 if (uceCtrlManager == null) {
Brad Ebingera68a4972020-01-30 17:31:23 -0800283 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
284 "This subscription does not support UCE.");
285 }
James.cf Lin99a360d2020-11-04 10:48:37 +0800286 uceCtrlManager.requestCapabilities(contactNumbers, c);
287 } catch (ImsException e) {
288 throw new ServiceSpecificException(e.getCode(), e.getMessage());
Brad Ebingera68a4972020-01-30 17:31:23 -0800289 } finally {
290 Binder.restoreCallingIdentity(token);
Brad Ebinger1aa94992020-01-22 14:17:23 -0800291 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800292 }
293
294 @Override
James.cf Linbcdf8b32021-01-14 16:44:13 +0800295 public void requestAvailability(int subId, String callingPackage,
James.cf Lin64e91212020-10-30 01:09:52 +0800296 String callingFeatureId, Uri contactNumber, IRcsUceControllerCallback c) {
James.cf Lin051dd252021-01-21 03:30:54 +0800297 enforceAccessUserCapabilityExchangePermission("requestAvailability");
298 enforceReadContactsPermission("requestAvailability");
Brad Ebingera68a4972020-01-30 17:31:23 -0800299 final long token = Binder.clearCallingIdentity();
300 try {
James.cf Lin99a360d2020-11-04 10:48:37 +0800301 UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
302 UceControllerManager.class);
303 if (uceCtrlManager == null) {
Brad Ebingera68a4972020-01-30 17:31:23 -0800304 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
305 "This subscription does not support UCE.");
306 }
James.cf Lin99a360d2020-11-04 10:48:37 +0800307 uceCtrlManager.requestNetworkAvailability(contactNumber, c);
308 } catch (ImsException e) {
309 throw new ServiceSpecificException(e.getCode(), e.getMessage());
310 } finally {
311 Binder.restoreCallingIdentity(token);
312 }
313 }
314
315 @Override
316 public @PublishState int getUcePublishState(int subId) {
317 enforceReadPrivilegedPermission("getUcePublishState");
318 final long token = Binder.clearCallingIdentity();
319 try {
320 UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
321 UceControllerManager.class);
322 if (uceCtrlManager == null) {
323 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
324 "This subscription does not support UCE.");
325 }
326 return uceCtrlManager.getUcePublishState();
327 } catch (ImsException e) {
328 throw new ServiceSpecificException(e.getCode(), e.getMessage());
329 } finally {
330 Binder.restoreCallingIdentity(token);
331 }
332 }
333
Brad Ebingerd4c5bde2021-02-12 06:18:28 +0000334 /**
335 * Add new feature tags to the Set used to calculate the capabilities in PUBLISH.
336 */
337 // Used for SHELL command only right now.
338 public RcsContactUceCapability addUceRegistrationOverrideShell(int subId,
339 Set<String> featureTags) throws ImsException {
340 // Permission check happening in PhoneInterfaceManager.
341 UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
342 UceControllerManager.class);
343 if (uceCtrlManager == null) {
344 return null;
345 }
346 return uceCtrlManager.addUceRegistrationOverride(featureTags);
347 }
348
349 /**
350 * Remove existing feature tags to the Set used to calculate the capabilities in PUBLISH.
351 */
352 // Used for SHELL command only right now.
353 public RcsContactUceCapability removeUceRegistrationOverrideShell(int subId,
354 Set<String> featureTags) throws ImsException {
355 // Permission check happening in PhoneInterfaceManager.
356 UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
357 UceControllerManager.class);
358 if (uceCtrlManager == null) {
359 return null;
360 }
361 return uceCtrlManager.removeUceRegistrationOverride(featureTags);
362 }
363
364 /**
365 * Clear all overrides in the Set used to calculate the capabilities in PUBLISH.
366 */
367 // Used for SHELL command only right now.
368 public RcsContactUceCapability clearUceRegistrationOverrideShell(int subId)
369 throws ImsException {
370 // Permission check happening in PhoneInterfaceManager.
371 UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
372 UceControllerManager.class);
373 if (uceCtrlManager == null) {
374 return null;
375 }
376 return uceCtrlManager.clearUceRegistrationOverride();
377 }
378
379 /**
380 * @return current RcsContactUceCapability instance that will be used for PUBLISH.
381 */
382 // Used for SHELL command only right now.
383 public RcsContactUceCapability getLatestRcsContactUceCapabilityShell(int subId)
384 throws ImsException {
385 // Permission check happening in PhoneInterfaceManager.
386 UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
387 UceControllerManager.class);
388 if (uceCtrlManager == null) {
389 return null;
390 }
391 return uceCtrlManager.getLatestRcsContactUceCapability();
392 }
393
394 /**
395 * @return the PIDf XML used in the last PUBLISH procedure or "none" if the device is not
396 * published. Returns {@code null} if the operation failed due to an error.
397 */
398 // Used for SHELL command only right now.
399 public String getLastUcePidfXmlShell(int subId) throws ImsException {
400 // Permission check happening in PhoneInterfaceManager.
401 UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
402 UceControllerManager.class);
403 if (uceCtrlManager == null) {
404 return null;
405 }
406 String pidfXml = uceCtrlManager.getLastPidfXml();
407 return pidfXml == null ? "none" : pidfXml;
408 }
409
James.cf Line8713a42021-04-29 16:04:26 +0800410 /**
411 * Remove UCE requests cannot be sent to the network status.
412 * @return true if this command is successful.
413 */
414 // Used for SHELL command only right now.
415 public boolean removeUceRequestDisallowedStatus(int subId) throws ImsException {
416 UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
417 UceControllerManager.class);
418 if (uceCtrlManager == null) {
419 return false;
420 }
421 return uceCtrlManager.removeUceRequestDisallowedStatus();
422 }
423
James.cf Lin0fc71b02021-05-25 01:37:38 +0800424 /**
425 * Set the timeout for contact capabilities request.
426 */
427 // Used for SHELL command only right now.
428 public boolean setCapabilitiesRequestTimeout(int subId, long timeoutAfter) throws ImsException {
429 UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
430 UceControllerManager.class);
431 if (uceCtrlManager == null) {
432 return false;
433 }
434 return uceCtrlManager.setCapabilitiesRequestTimeout(timeoutAfter);
435 }
436
James.cf Lin99a360d2020-11-04 10:48:37 +0800437 @Override
438 public void registerUcePublishStateCallback(int subId, IRcsUcePublishStateCallback c) {
439 enforceReadPrivilegedPermission("registerUcePublishStateCallback");
440 final long token = Binder.clearCallingIdentity();
441 try {
442 UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
443 UceControllerManager.class);
444 if (uceCtrlManager == null) {
445 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
446 "This subscription does not support UCE.");
447 }
448 uceCtrlManager.registerPublishStateCallback(c);
449 } catch (ImsException e) {
450 throw new ServiceSpecificException(e.getCode(), e.getMessage());
451 } finally {
452 Binder.restoreCallingIdentity(token);
453 }
454 }
455
456 @Override
457 public void unregisterUcePublishStateCallback(int subId, IRcsUcePublishStateCallback c) {
458 enforceReadPrivilegedPermission("unregisterUcePublishStateCallback");
459 final long token = Binder.clearCallingIdentity();
460 try {
461 UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
462 UceControllerManager.class);
463 if (uceCtrlManager == null) {
464 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
465 "This subscription does not support UCE.");
466 }
467 uceCtrlManager.unregisterPublishStateCallback(c);
Brad Ebingera68a4972020-01-30 17:31:23 -0800468 } finally {
469 Binder.restoreCallingIdentity(token);
Brad Ebinger1aa94992020-01-22 14:17:23 -0800470 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800471 }
472
473 @Override
Brad Ebinger8b79edc2020-02-27 19:13:24 -0800474 public boolean isUceSettingEnabled(int subId, String callingPackage, String callingFeatureId) {
475 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
476 mApp, subId, callingPackage, callingFeatureId, "isUceSettingEnabled")) {
477 Log.w(TAG, "isUceSettingEnabled: READ_PHONE_STATE app op disabled when accessing "
478 + "isUceSettingEnabled");
479 return false;
480 }
481 final long token = Binder.clearCallingIdentity();
482 try {
483 return SubscriptionManager.getBooleanSubscriptionProperty(subId,
484 SubscriptionManager.IMS_RCS_UCE_ENABLED, false /*defaultValue*/, mApp);
485 } finally {
486 Binder.restoreCallingIdentity(token);
487 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800488 }
489
490 @Override
491 public void setUceSettingEnabled(int subId, boolean isEnabled) {
492 enforceModifyPermission();
Brad Ebinger8b79edc2020-02-27 19:13:24 -0800493 final long token = Binder.clearCallingIdentity();
494 try {
495 SubscriptionManager.setSubscriptionProperty(subId,
496 SubscriptionManager.IMS_RCS_UCE_ENABLED, (isEnabled ? "1" : "0"));
497 } finally {
498 Binder.restoreCallingIdentity(token);
499 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800500 }
501
Brad Ebingerb989c7c2020-09-23 17:03:48 -0700502 @Override
503 public boolean isSipDelegateSupported(int subId) {
Brad Ebinger4df7e242021-02-17 23:23:21 +0000504 TelephonyPermissions.enforceAnyPermissionGranted(mApp, Binder.getCallingUid(),
505 "isSipDelegateSupported",
506 Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION,
507 Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
Brad Ebinger49a72b42021-01-29 00:55:24 +0000508 if (!isImsSingleRegistrationSupportedOnDevice()) {
509 return false;
510 }
Brad Ebingerb989c7c2020-09-23 17:03:48 -0700511 final long token = Binder.clearCallingIdentity();
512 try {
513 SipTransportController transport = getRcsFeatureController(subId).getFeature(
514 SipTransportController.class);
515 if (transport == null) {
516 return false;
517 }
518 return transport.isSupported(subId);
519 } catch (ImsException e) {
520 throw new ServiceSpecificException(e.getCode(), e.getMessage());
521 } catch (ServiceSpecificException e) {
522 if (e.errorCode == ImsException.CODE_ERROR_UNSUPPORTED_OPERATION) {
523 return false;
524 }
525 throw e;
526 } finally {
527 Binder.restoreCallingIdentity(token);
528 }
529 }
530
Brad Ebingeraf1e9832020-10-14 10:49:28 -0700531 @Override
Brad Ebinger63b6f5a2020-10-27 11:43:35 -0700532 public void createSipDelegate(int subId, DelegateRequest request, String packageName,
Brad Ebingeraf1e9832020-10-14 10:49:28 -0700533 ISipDelegateConnectionStateCallback delegateState,
534 ISipDelegateMessageCallback delegateMessage) {
Brad Ebinger4df7e242021-02-17 23:23:21 +0000535 enforceImsSingleRegistrationPermission("createSipDelegate");
Brad Ebinger49a72b42021-01-29 00:55:24 +0000536 if (!isImsSingleRegistrationSupportedOnDevice()) {
537 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
538 "SipDelegate creation is only supported for devices supporting IMS single "
539 + "registration");
540 }
Brad Ebinger63b6f5a2020-10-27 11:43:35 -0700541 if (!UserHandle.getUserHandleForUid(Binder.getCallingUid()).isSystem()) {
542 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
543 "SipDelegate creation is only available to primary user.");
544 }
545 try {
546 int remoteUid = mApp.getPackageManager().getPackageUid(packageName, 0 /*flags*/);
547 if (Binder.getCallingUid() != remoteUid) {
548 throw new SecurityException("passed in packageName does not match the caller");
549 }
550 } catch (PackageManager.NameNotFoundException e) {
551 throw new SecurityException("Passed in PackageName can not be found on device");
552 }
Brad Ebingeraf1e9832020-10-14 10:49:28 -0700553
554 final long identity = Binder.clearCallingIdentity();
555 SipTransportController transport = getRcsFeatureController(subId).getFeature(
556 SipTransportController.class);
557 if (transport == null) {
558 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
559 "This subscription does not support the creation of SIP delegates");
560 }
561 try {
Brad Ebinger63b6f5a2020-10-27 11:43:35 -0700562 transport.createSipDelegate(subId, request, packageName, delegateState,
563 delegateMessage);
Brad Ebingeraf1e9832020-10-14 10:49:28 -0700564 } catch (ImsException e) {
565 throw new ServiceSpecificException(e.getCode(), e.getMessage());
566 } finally {
567 Binder.restoreCallingIdentity(identity);
568 }
569 }
570
571 @Override
572 public void destroySipDelegate(int subId, ISipDelegate connection, int reason) {
Brad Ebinger4df7e242021-02-17 23:23:21 +0000573 enforceImsSingleRegistrationPermission("destroySipDelegate");
Brad Ebingeraf1e9832020-10-14 10:49:28 -0700574
575 final long identity = Binder.clearCallingIdentity();
576 try {
Brad Ebinger63b6f5a2020-10-27 11:43:35 -0700577 SipTransportController transport = getRcsFeatureController(subId).getFeature(
578 SipTransportController.class);
579 if (transport == null) {
580 return;
581 }
582 transport.destroySipDelegate(subId, connection, reason);
Brad Ebingeraf1e9832020-10-14 10:49:28 -0700583 } finally {
584 Binder.restoreCallingIdentity(identity);
585 }
586 }
587
Brad Ebinger36221382020-12-09 00:33:39 +0000588 @Override
589 public void triggerNetworkRegistration(int subId, ISipDelegate connection, int sipCode,
590 String sipReason) {
Brad Ebinger4df7e242021-02-17 23:23:21 +0000591 enforceImsSingleRegistrationPermission("triggerNetworkRegistration");
Brad Ebinger36221382020-12-09 00:33:39 +0000592
593 final long identity = Binder.clearCallingIdentity();
594 try {
595 SipTransportController transport = getRcsFeatureController(subId).getFeature(
596 SipTransportController.class);
597 if (transport == null) {
598 return;
599 }
600 transport.triggerFullNetworkRegistration(subId, connection, sipCode, sipReason);
601 } finally {
602 Binder.restoreCallingIdentity(identity);
603 }
604 }
605
James.cf Linaf3183c2019-10-24 00:59:00 +0800606 /**
Brad Ebingere3ae65a2020-09-11 12:45:11 -0700607 * Registers for updates to the RcsFeature connection through the IImsServiceFeatureCallback
608 * callback.
609 */
610 @Override
Brad Ebinger6366ce92020-10-01 13:51:05 -0700611 public void registerRcsFeatureCallback(int slotId, IImsServiceFeatureCallback callback) {
Brad Ebingere3ae65a2020-09-11 12:45:11 -0700612 enforceModifyPermission();
613
614 final long identity = Binder.clearCallingIdentity();
615 try {
616 if (mImsResolver == null) {
617 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
618 "Device does not support IMS");
619 }
Brad Ebinger6366ce92020-10-01 13:51:05 -0700620 mImsResolver.listenForFeature(slotId, ImsFeature.FEATURE_RCS, callback);
Brad Ebingere3ae65a2020-09-11 12:45:11 -0700621 } finally {
622 Binder.restoreCallingIdentity(identity);
623 }
624 }
Brad Ebinger6366ce92020-10-01 13:51:05 -0700625
Brad Ebingere3ae65a2020-09-11 12:45:11 -0700626 /**
627 * Unregister a previously registered IImsServiceFeatureCallback associated with an ImsFeature.
628 */
629 @Override
630 public void unregisterImsFeatureCallback(IImsServiceFeatureCallback callback) {
631 enforceModifyPermission();
632
633 final long identity = Binder.clearCallingIdentity();
634 try {
635 if (mImsResolver == null) return;
636 mImsResolver.unregisterImsFeatureCallback(callback);
637 } finally {
638 Binder.restoreCallingIdentity(identity);
639 }
640 }
641
642 /**
James.cf Linaf3183c2019-10-24 00:59:00 +0800643 * Make sure either called from same process as self (phone) or IPC caller has read privilege.
644 *
645 * @throws SecurityException if the caller does not have the required permission
646 */
647 private void enforceReadPrivilegedPermission(String message) {
648 mApp.enforceCallingOrSelfPermission(
649 android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, message);
650 }
651
652 /**
Brad Ebinger4df7e242021-02-17 23:23:21 +0000653 * @throws SecurityException if the caller does not have the required
654 * PERFORM_IMS_SINGLE_REGISTRATION permission.
655 */
656 private void enforceImsSingleRegistrationPermission(String message) {
657 mApp.enforceCallingOrSelfPermission(
658 Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION, message);
659 }
660
661 /**
James.cf Linaf3183c2019-10-24 00:59:00 +0800662 * Make sure the caller has the MODIFY_PHONE_STATE permission.
663 *
664 * @throws SecurityException if the caller does not have the required permission
665 */
666 private void enforceModifyPermission() {
667 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE, null);
668 }
James.cf Lincad981c2019-12-10 20:37:56 +0800669
670 /**
James.cf Lin051dd252021-01-21 03:30:54 +0800671 * Make sure the caller has the ACCESS_RCS_USER_CAPABILITY_EXCHANGE permission.
672 *
673 * @throws SecurityException if the caller does not have the required permission.
674 */
675 private void enforceAccessUserCapabilityExchangePermission(String message) {
676 mApp.enforceCallingOrSelfPermission(
677 android.Manifest.permission.ACCESS_RCS_USER_CAPABILITY_EXCHANGE, message);
678 }
679
680 /**
681 * Make sure the caller has the READ_CONTACTS permission.
682 *
683 * @throws SecurityException if the caller does not have the required permission.
684 */
685 private void enforceReadContactsPermission(String message) {
686 mApp.enforceCallingOrSelfPermission(
687 android.Manifest.permission.READ_CONTACTS, message);
688 }
689
690 /**
James.cf Lindc2d5422019-12-31 14:40:25 +0800691 * Retrieve ImsPhone instance.
James.cf Lincad981c2019-12-10 20:37:56 +0800692 *
693 * @param subId the subscription ID
James.cf Lindc2d5422019-12-31 14:40:25 +0800694 * @return The ImsPhone instance
695 * @throws ServiceSpecificException if getting ImsPhone instance failed.
James.cf Lincad981c2019-12-10 20:37:56 +0800696 */
James.cf Lindc2d5422019-12-31 14:40:25 +0800697 private ImsPhone getImsPhone(int subId) {
698 if (!ImsManager.isImsSupportedOnDevice(mApp)) {
699 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
700 "IMS is not available on device.");
701 }
James.cf Lincad981c2019-12-10 20:37:56 +0800702 Phone phone = PhoneGlobals.getPhone(subId);
703 if (phone == null) {
704 throw new ServiceSpecificException(ImsException.CODE_ERROR_INVALID_SUBSCRIPTION,
705 "Invalid subscription Id: " + subId);
706 }
707 ImsPhone imsPhone = (ImsPhone) phone.getImsPhone();
708 if (imsPhone == null) {
James.cf Lindc2d5422019-12-31 14:40:25 +0800709 throw new ServiceSpecificException(ImsException.CODE_ERROR_SERVICE_UNAVAILABLE,
710 "Cannot find ImsPhone instance: " + subId);
711 }
712 return imsPhone;
713 }
714
715 /**
716 * Retrieve RcsFeatureManager instance.
717 *
718 * @param subId the subscription ID
719 * @return The RcsFeatureManager instance
720 * @throws ServiceSpecificException if getting RcsFeatureManager instance failed.
721 */
Brad Ebingera68a4972020-01-30 17:31:23 -0800722 private RcsFeatureController getRcsFeatureController(int subId) {
James.cf Lindc2d5422019-12-31 14:40:25 +0800723 if (!ImsManager.isImsSupportedOnDevice(mApp)) {
James.cf Lincad981c2019-12-10 20:37:56 +0800724 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
James.cf Lindc2d5422019-12-31 14:40:25 +0800725 "IMS is not available on device.");
726 }
Brad Ebingera68a4972020-01-30 17:31:23 -0800727 if (mRcsService == null) {
728 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
729 "IMS is not available on device.");
730 }
James.cf Lindc2d5422019-12-31 14:40:25 +0800731 Phone phone = PhoneGlobals.getPhone(subId);
732 if (phone == null) {
733 throw new ServiceSpecificException(ImsException.CODE_ERROR_INVALID_SUBSCRIPTION,
734 "Invalid subscription Id: " + subId);
735 }
Brad Ebingera68a4972020-01-30 17:31:23 -0800736 int slotId = phone.getPhoneId();
737 RcsFeatureController c = mRcsService.getFeatureController(slotId);
738 if (c == null) {
Brad Ebinger036dc9e2020-02-06 15:49:06 -0800739 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
740 "The requested operation is not supported for subId " + subId);
James.cf Lincad981c2019-12-10 20:37:56 +0800741 }
Brad Ebingera68a4972020-01-30 17:31:23 -0800742 return c;
James.cf Lincad981c2019-12-10 20:37:56 +0800743 }
James.cf Linc9f35a42020-01-15 02:35:22 +0800744
Brad Ebinger49a72b42021-01-29 00:55:24 +0000745 private boolean isImsSingleRegistrationSupportedOnDevice() {
746 return mSingleRegistrationOverride != null ? mSingleRegistrationOverride
747 : mApp.getPackageManager().hasSystemFeature(
748 PackageManager.FEATURE_TELEPHONY_IMS_SINGLE_REGISTRATION);
749 }
750
James.cf Linc9f35a42020-01-15 02:35:22 +0800751 void setRcsService(TelephonyRcsService rcsService) {
752 mRcsService = rcsService;
753 }
Brad Ebinger49a72b42021-01-29 00:55:24 +0000754
755 /**
756 * Override device RCS single registration support check for CTS testing or remove override
757 * if the Boolean is set to null.
758 */
759 void setDeviceSingleRegistrationSupportOverride(Boolean deviceOverrideValue) {
760 mSingleRegistrationOverride = deviceOverrideValue;
761 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800762}