blob: 90c9df4fe6123cdac4c625c0208f4d72ce31acd9 [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 Lin99a360d2020-11-04 10:48:37 +0800424 @Override
425 public void registerUcePublishStateCallback(int subId, IRcsUcePublishStateCallback c) {
426 enforceReadPrivilegedPermission("registerUcePublishStateCallback");
427 final long token = Binder.clearCallingIdentity();
428 try {
429 UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
430 UceControllerManager.class);
431 if (uceCtrlManager == null) {
432 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
433 "This subscription does not support UCE.");
434 }
435 uceCtrlManager.registerPublishStateCallback(c);
436 } catch (ImsException e) {
437 throw new ServiceSpecificException(e.getCode(), e.getMessage());
438 } finally {
439 Binder.restoreCallingIdentity(token);
440 }
441 }
442
443 @Override
444 public void unregisterUcePublishStateCallback(int subId, IRcsUcePublishStateCallback c) {
445 enforceReadPrivilegedPermission("unregisterUcePublishStateCallback");
446 final long token = Binder.clearCallingIdentity();
447 try {
448 UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
449 UceControllerManager.class);
450 if (uceCtrlManager == null) {
451 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
452 "This subscription does not support UCE.");
453 }
454 uceCtrlManager.unregisterPublishStateCallback(c);
Brad Ebingera68a4972020-01-30 17:31:23 -0800455 } finally {
456 Binder.restoreCallingIdentity(token);
Brad Ebinger1aa94992020-01-22 14:17:23 -0800457 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800458 }
459
460 @Override
Brad Ebinger8b79edc2020-02-27 19:13:24 -0800461 public boolean isUceSettingEnabled(int subId, String callingPackage, String callingFeatureId) {
462 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
463 mApp, subId, callingPackage, callingFeatureId, "isUceSettingEnabled")) {
464 Log.w(TAG, "isUceSettingEnabled: READ_PHONE_STATE app op disabled when accessing "
465 + "isUceSettingEnabled");
466 return false;
467 }
468 final long token = Binder.clearCallingIdentity();
469 try {
470 return SubscriptionManager.getBooleanSubscriptionProperty(subId,
471 SubscriptionManager.IMS_RCS_UCE_ENABLED, false /*defaultValue*/, mApp);
472 } finally {
473 Binder.restoreCallingIdentity(token);
474 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800475 }
476
477 @Override
478 public void setUceSettingEnabled(int subId, boolean isEnabled) {
479 enforceModifyPermission();
Brad Ebinger8b79edc2020-02-27 19:13:24 -0800480 final long token = Binder.clearCallingIdentity();
481 try {
482 SubscriptionManager.setSubscriptionProperty(subId,
483 SubscriptionManager.IMS_RCS_UCE_ENABLED, (isEnabled ? "1" : "0"));
484 } finally {
485 Binder.restoreCallingIdentity(token);
486 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800487 }
488
Brad Ebingerb989c7c2020-09-23 17:03:48 -0700489 @Override
490 public boolean isSipDelegateSupported(int subId) {
Brad Ebinger4df7e242021-02-17 23:23:21 +0000491 TelephonyPermissions.enforceAnyPermissionGranted(mApp, Binder.getCallingUid(),
492 "isSipDelegateSupported",
493 Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION,
494 Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
Brad Ebinger49a72b42021-01-29 00:55:24 +0000495 if (!isImsSingleRegistrationSupportedOnDevice()) {
496 return false;
497 }
Brad Ebingerb989c7c2020-09-23 17:03:48 -0700498 final long token = Binder.clearCallingIdentity();
499 try {
500 SipTransportController transport = getRcsFeatureController(subId).getFeature(
501 SipTransportController.class);
502 if (transport == null) {
503 return false;
504 }
505 return transport.isSupported(subId);
506 } catch (ImsException e) {
507 throw new ServiceSpecificException(e.getCode(), e.getMessage());
508 } catch (ServiceSpecificException e) {
509 if (e.errorCode == ImsException.CODE_ERROR_UNSUPPORTED_OPERATION) {
510 return false;
511 }
512 throw e;
513 } finally {
514 Binder.restoreCallingIdentity(token);
515 }
516 }
517
Brad Ebingeraf1e9832020-10-14 10:49:28 -0700518 @Override
Brad Ebinger63b6f5a2020-10-27 11:43:35 -0700519 public void createSipDelegate(int subId, DelegateRequest request, String packageName,
Brad Ebingeraf1e9832020-10-14 10:49:28 -0700520 ISipDelegateConnectionStateCallback delegateState,
521 ISipDelegateMessageCallback delegateMessage) {
Brad Ebinger4df7e242021-02-17 23:23:21 +0000522 enforceImsSingleRegistrationPermission("createSipDelegate");
Brad Ebinger49a72b42021-01-29 00:55:24 +0000523 if (!isImsSingleRegistrationSupportedOnDevice()) {
524 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
525 "SipDelegate creation is only supported for devices supporting IMS single "
526 + "registration");
527 }
Brad Ebinger63b6f5a2020-10-27 11:43:35 -0700528 if (!UserHandle.getUserHandleForUid(Binder.getCallingUid()).isSystem()) {
529 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
530 "SipDelegate creation is only available to primary user.");
531 }
532 try {
533 int remoteUid = mApp.getPackageManager().getPackageUid(packageName, 0 /*flags*/);
534 if (Binder.getCallingUid() != remoteUid) {
535 throw new SecurityException("passed in packageName does not match the caller");
536 }
537 } catch (PackageManager.NameNotFoundException e) {
538 throw new SecurityException("Passed in PackageName can not be found on device");
539 }
Brad Ebingeraf1e9832020-10-14 10:49:28 -0700540
541 final long identity = Binder.clearCallingIdentity();
542 SipTransportController transport = getRcsFeatureController(subId).getFeature(
543 SipTransportController.class);
544 if (transport == null) {
545 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
546 "This subscription does not support the creation of SIP delegates");
547 }
548 try {
Brad Ebinger63b6f5a2020-10-27 11:43:35 -0700549 transport.createSipDelegate(subId, request, packageName, delegateState,
550 delegateMessage);
Brad Ebingeraf1e9832020-10-14 10:49:28 -0700551 } catch (ImsException e) {
552 throw new ServiceSpecificException(e.getCode(), e.getMessage());
553 } finally {
554 Binder.restoreCallingIdentity(identity);
555 }
556 }
557
558 @Override
559 public void destroySipDelegate(int subId, ISipDelegate connection, int reason) {
Brad Ebinger4df7e242021-02-17 23:23:21 +0000560 enforceImsSingleRegistrationPermission("destroySipDelegate");
Brad Ebingeraf1e9832020-10-14 10:49:28 -0700561
562 final long identity = Binder.clearCallingIdentity();
563 try {
Brad Ebinger63b6f5a2020-10-27 11:43:35 -0700564 SipTransportController transport = getRcsFeatureController(subId).getFeature(
565 SipTransportController.class);
566 if (transport == null) {
567 return;
568 }
569 transport.destroySipDelegate(subId, connection, reason);
Brad Ebingeraf1e9832020-10-14 10:49:28 -0700570 } finally {
571 Binder.restoreCallingIdentity(identity);
572 }
573 }
574
Brad Ebinger36221382020-12-09 00:33:39 +0000575 @Override
576 public void triggerNetworkRegistration(int subId, ISipDelegate connection, int sipCode,
577 String sipReason) {
Brad Ebinger4df7e242021-02-17 23:23:21 +0000578 enforceImsSingleRegistrationPermission("triggerNetworkRegistration");
Brad Ebinger36221382020-12-09 00:33:39 +0000579
580 final long identity = Binder.clearCallingIdentity();
581 try {
582 SipTransportController transport = getRcsFeatureController(subId).getFeature(
583 SipTransportController.class);
584 if (transport == null) {
585 return;
586 }
587 transport.triggerFullNetworkRegistration(subId, connection, sipCode, sipReason);
588 } finally {
589 Binder.restoreCallingIdentity(identity);
590 }
591 }
592
James.cf Linaf3183c2019-10-24 00:59:00 +0800593 /**
Brad Ebingere3ae65a2020-09-11 12:45:11 -0700594 * Registers for updates to the RcsFeature connection through the IImsServiceFeatureCallback
595 * callback.
596 */
597 @Override
Brad Ebinger6366ce92020-10-01 13:51:05 -0700598 public void registerRcsFeatureCallback(int slotId, IImsServiceFeatureCallback callback) {
Brad Ebingere3ae65a2020-09-11 12:45:11 -0700599 enforceModifyPermission();
600
601 final long identity = Binder.clearCallingIdentity();
602 try {
603 if (mImsResolver == null) {
604 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
605 "Device does not support IMS");
606 }
Brad Ebinger6366ce92020-10-01 13:51:05 -0700607 mImsResolver.listenForFeature(slotId, ImsFeature.FEATURE_RCS, callback);
Brad Ebingere3ae65a2020-09-11 12:45:11 -0700608 } finally {
609 Binder.restoreCallingIdentity(identity);
610 }
611 }
Brad Ebinger6366ce92020-10-01 13:51:05 -0700612
Brad Ebingere3ae65a2020-09-11 12:45:11 -0700613 /**
614 * Unregister a previously registered IImsServiceFeatureCallback associated with an ImsFeature.
615 */
616 @Override
617 public void unregisterImsFeatureCallback(IImsServiceFeatureCallback callback) {
618 enforceModifyPermission();
619
620 final long identity = Binder.clearCallingIdentity();
621 try {
622 if (mImsResolver == null) return;
623 mImsResolver.unregisterImsFeatureCallback(callback);
624 } finally {
625 Binder.restoreCallingIdentity(identity);
626 }
627 }
628
629 /**
James.cf Linaf3183c2019-10-24 00:59:00 +0800630 * Make sure either called from same process as self (phone) or IPC caller has read privilege.
631 *
632 * @throws SecurityException if the caller does not have the required permission
633 */
634 private void enforceReadPrivilegedPermission(String message) {
635 mApp.enforceCallingOrSelfPermission(
636 android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, message);
637 }
638
639 /**
Brad Ebinger4df7e242021-02-17 23:23:21 +0000640 * @throws SecurityException if the caller does not have the required
641 * PERFORM_IMS_SINGLE_REGISTRATION permission.
642 */
643 private void enforceImsSingleRegistrationPermission(String message) {
644 mApp.enforceCallingOrSelfPermission(
645 Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION, message);
646 }
647
648 /**
James.cf Linaf3183c2019-10-24 00:59:00 +0800649 * Make sure the caller has the MODIFY_PHONE_STATE permission.
650 *
651 * @throws SecurityException if the caller does not have the required permission
652 */
653 private void enforceModifyPermission() {
654 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE, null);
655 }
James.cf Lincad981c2019-12-10 20:37:56 +0800656
657 /**
James.cf Lin051dd252021-01-21 03:30:54 +0800658 * Make sure the caller has the ACCESS_RCS_USER_CAPABILITY_EXCHANGE permission.
659 *
660 * @throws SecurityException if the caller does not have the required permission.
661 */
662 private void enforceAccessUserCapabilityExchangePermission(String message) {
663 mApp.enforceCallingOrSelfPermission(
664 android.Manifest.permission.ACCESS_RCS_USER_CAPABILITY_EXCHANGE, message);
665 }
666
667 /**
668 * Make sure the caller has the READ_CONTACTS permission.
669 *
670 * @throws SecurityException if the caller does not have the required permission.
671 */
672 private void enforceReadContactsPermission(String message) {
673 mApp.enforceCallingOrSelfPermission(
674 android.Manifest.permission.READ_CONTACTS, message);
675 }
676
677 /**
James.cf Lindc2d5422019-12-31 14:40:25 +0800678 * Retrieve ImsPhone instance.
James.cf Lincad981c2019-12-10 20:37:56 +0800679 *
680 * @param subId the subscription ID
James.cf Lindc2d5422019-12-31 14:40:25 +0800681 * @return The ImsPhone instance
682 * @throws ServiceSpecificException if getting ImsPhone instance failed.
James.cf Lincad981c2019-12-10 20:37:56 +0800683 */
James.cf Lindc2d5422019-12-31 14:40:25 +0800684 private ImsPhone getImsPhone(int subId) {
685 if (!ImsManager.isImsSupportedOnDevice(mApp)) {
686 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
687 "IMS is not available on device.");
688 }
James.cf Lincad981c2019-12-10 20:37:56 +0800689 Phone phone = PhoneGlobals.getPhone(subId);
690 if (phone == null) {
691 throw new ServiceSpecificException(ImsException.CODE_ERROR_INVALID_SUBSCRIPTION,
692 "Invalid subscription Id: " + subId);
693 }
694 ImsPhone imsPhone = (ImsPhone) phone.getImsPhone();
695 if (imsPhone == null) {
James.cf Lindc2d5422019-12-31 14:40:25 +0800696 throw new ServiceSpecificException(ImsException.CODE_ERROR_SERVICE_UNAVAILABLE,
697 "Cannot find ImsPhone instance: " + subId);
698 }
699 return imsPhone;
700 }
701
702 /**
703 * Retrieve RcsFeatureManager instance.
704 *
705 * @param subId the subscription ID
706 * @return The RcsFeatureManager instance
707 * @throws ServiceSpecificException if getting RcsFeatureManager instance failed.
708 */
Brad Ebingera68a4972020-01-30 17:31:23 -0800709 private RcsFeatureController getRcsFeatureController(int subId) {
James.cf Lindc2d5422019-12-31 14:40:25 +0800710 if (!ImsManager.isImsSupportedOnDevice(mApp)) {
James.cf Lincad981c2019-12-10 20:37:56 +0800711 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
James.cf Lindc2d5422019-12-31 14:40:25 +0800712 "IMS is not available on device.");
713 }
Brad Ebingera68a4972020-01-30 17:31:23 -0800714 if (mRcsService == null) {
715 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
716 "IMS is not available on device.");
717 }
James.cf Lindc2d5422019-12-31 14:40:25 +0800718 Phone phone = PhoneGlobals.getPhone(subId);
719 if (phone == null) {
720 throw new ServiceSpecificException(ImsException.CODE_ERROR_INVALID_SUBSCRIPTION,
721 "Invalid subscription Id: " + subId);
722 }
Brad Ebingera68a4972020-01-30 17:31:23 -0800723 int slotId = phone.getPhoneId();
724 RcsFeatureController c = mRcsService.getFeatureController(slotId);
725 if (c == null) {
Brad Ebinger036dc9e2020-02-06 15:49:06 -0800726 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
727 "The requested operation is not supported for subId " + subId);
James.cf Lincad981c2019-12-10 20:37:56 +0800728 }
Brad Ebingera68a4972020-01-30 17:31:23 -0800729 return c;
James.cf Lincad981c2019-12-10 20:37:56 +0800730 }
James.cf Linc9f35a42020-01-15 02:35:22 +0800731
Brad Ebinger49a72b42021-01-29 00:55:24 +0000732 private boolean isImsSingleRegistrationSupportedOnDevice() {
733 return mSingleRegistrationOverride != null ? mSingleRegistrationOverride
734 : mApp.getPackageManager().hasSystemFeature(
735 PackageManager.FEATURE_TELEPHONY_IMS_SINGLE_REGISTRATION);
736 }
737
James.cf Linc9f35a42020-01-15 02:35:22 +0800738 void setRcsService(TelephonyRcsService rcsService) {
739 mRcsService = rcsService;
740 }
Brad Ebinger49a72b42021-01-29 00:55:24 +0000741
742 /**
743 * Override device RCS single registration support check for CTS testing or remove override
744 * if the Boolean is set to null.
745 */
746 void setDeviceSingleRegistrationSupportOverride(Boolean deviceOverrideValue) {
747 mSingleRegistrationOverride = deviceOverrideValue;
748 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800749}