blob: 31059e7ec080f6b55eac7c9e7a495899091e0ebc [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 Ebingere3ae65a2020-09-11 12:45:11 -070097 mImsResolver = mApp.getImsResolver();
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 Lin99a360d2020-11-04 10:48:37 +0800410 @Override
411 public void registerUcePublishStateCallback(int subId, IRcsUcePublishStateCallback c) {
412 enforceReadPrivilegedPermission("registerUcePublishStateCallback");
413 final long token = Binder.clearCallingIdentity();
414 try {
415 UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
416 UceControllerManager.class);
417 if (uceCtrlManager == null) {
418 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
419 "This subscription does not support UCE.");
420 }
421 uceCtrlManager.registerPublishStateCallback(c);
422 } catch (ImsException e) {
423 throw new ServiceSpecificException(e.getCode(), e.getMessage());
424 } finally {
425 Binder.restoreCallingIdentity(token);
426 }
427 }
428
429 @Override
430 public void unregisterUcePublishStateCallback(int subId, IRcsUcePublishStateCallback c) {
431 enforceReadPrivilegedPermission("unregisterUcePublishStateCallback");
432 final long token = Binder.clearCallingIdentity();
433 try {
434 UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
435 UceControllerManager.class);
436 if (uceCtrlManager == null) {
437 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
438 "This subscription does not support UCE.");
439 }
440 uceCtrlManager.unregisterPublishStateCallback(c);
Brad Ebingera68a4972020-01-30 17:31:23 -0800441 } finally {
442 Binder.restoreCallingIdentity(token);
Brad Ebinger1aa94992020-01-22 14:17:23 -0800443 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800444 }
445
446 @Override
Brad Ebinger8b79edc2020-02-27 19:13:24 -0800447 public boolean isUceSettingEnabled(int subId, String callingPackage, String callingFeatureId) {
448 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
449 mApp, subId, callingPackage, callingFeatureId, "isUceSettingEnabled")) {
450 Log.w(TAG, "isUceSettingEnabled: READ_PHONE_STATE app op disabled when accessing "
451 + "isUceSettingEnabled");
452 return false;
453 }
454 final long token = Binder.clearCallingIdentity();
455 try {
456 return SubscriptionManager.getBooleanSubscriptionProperty(subId,
457 SubscriptionManager.IMS_RCS_UCE_ENABLED, false /*defaultValue*/, mApp);
458 } finally {
459 Binder.restoreCallingIdentity(token);
460 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800461 }
462
463 @Override
464 public void setUceSettingEnabled(int subId, boolean isEnabled) {
465 enforceModifyPermission();
Brad Ebinger8b79edc2020-02-27 19:13:24 -0800466 final long token = Binder.clearCallingIdentity();
467 try {
468 SubscriptionManager.setSubscriptionProperty(subId,
469 SubscriptionManager.IMS_RCS_UCE_ENABLED, (isEnabled ? "1" : "0"));
470 } finally {
471 Binder.restoreCallingIdentity(token);
472 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800473 }
474
Brad Ebingerb989c7c2020-09-23 17:03:48 -0700475 @Override
476 public boolean isSipDelegateSupported(int subId) {
Brad Ebinger4df7e242021-02-17 23:23:21 +0000477 TelephonyPermissions.enforceAnyPermissionGranted(mApp, Binder.getCallingUid(),
478 "isSipDelegateSupported",
479 Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION,
480 Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
Brad Ebinger49a72b42021-01-29 00:55:24 +0000481 if (!isImsSingleRegistrationSupportedOnDevice()) {
482 return false;
483 }
Brad Ebingerb989c7c2020-09-23 17:03:48 -0700484 final long token = Binder.clearCallingIdentity();
485 try {
486 SipTransportController transport = getRcsFeatureController(subId).getFeature(
487 SipTransportController.class);
488 if (transport == null) {
489 return false;
490 }
491 return transport.isSupported(subId);
492 } catch (ImsException e) {
493 throw new ServiceSpecificException(e.getCode(), e.getMessage());
494 } catch (ServiceSpecificException e) {
495 if (e.errorCode == ImsException.CODE_ERROR_UNSUPPORTED_OPERATION) {
496 return false;
497 }
498 throw e;
499 } finally {
500 Binder.restoreCallingIdentity(token);
501 }
502 }
503
Brad Ebingeraf1e9832020-10-14 10:49:28 -0700504 @Override
Brad Ebinger63b6f5a2020-10-27 11:43:35 -0700505 public void createSipDelegate(int subId, DelegateRequest request, String packageName,
Brad Ebingeraf1e9832020-10-14 10:49:28 -0700506 ISipDelegateConnectionStateCallback delegateState,
507 ISipDelegateMessageCallback delegateMessage) {
Brad Ebinger4df7e242021-02-17 23:23:21 +0000508 enforceImsSingleRegistrationPermission("createSipDelegate");
Brad Ebinger49a72b42021-01-29 00:55:24 +0000509 if (!isImsSingleRegistrationSupportedOnDevice()) {
510 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
511 "SipDelegate creation is only supported for devices supporting IMS single "
512 + "registration");
513 }
Brad Ebinger63b6f5a2020-10-27 11:43:35 -0700514 if (!UserHandle.getUserHandleForUid(Binder.getCallingUid()).isSystem()) {
515 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
516 "SipDelegate creation is only available to primary user.");
517 }
518 try {
519 int remoteUid = mApp.getPackageManager().getPackageUid(packageName, 0 /*flags*/);
520 if (Binder.getCallingUid() != remoteUid) {
521 throw new SecurityException("passed in packageName does not match the caller");
522 }
523 } catch (PackageManager.NameNotFoundException e) {
524 throw new SecurityException("Passed in PackageName can not be found on device");
525 }
Brad Ebingeraf1e9832020-10-14 10:49:28 -0700526
527 final long identity = Binder.clearCallingIdentity();
528 SipTransportController transport = getRcsFeatureController(subId).getFeature(
529 SipTransportController.class);
530 if (transport == null) {
531 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
532 "This subscription does not support the creation of SIP delegates");
533 }
534 try {
Brad Ebinger63b6f5a2020-10-27 11:43:35 -0700535 transport.createSipDelegate(subId, request, packageName, delegateState,
536 delegateMessage);
Brad Ebingeraf1e9832020-10-14 10:49:28 -0700537 } catch (ImsException e) {
538 throw new ServiceSpecificException(e.getCode(), e.getMessage());
539 } finally {
540 Binder.restoreCallingIdentity(identity);
541 }
542 }
543
544 @Override
545 public void destroySipDelegate(int subId, ISipDelegate connection, int reason) {
Brad Ebinger4df7e242021-02-17 23:23:21 +0000546 enforceImsSingleRegistrationPermission("destroySipDelegate");
Brad Ebingeraf1e9832020-10-14 10:49:28 -0700547
548 final long identity = Binder.clearCallingIdentity();
549 try {
Brad Ebinger63b6f5a2020-10-27 11:43:35 -0700550 SipTransportController transport = getRcsFeatureController(subId).getFeature(
551 SipTransportController.class);
552 if (transport == null) {
553 return;
554 }
555 transport.destroySipDelegate(subId, connection, reason);
Brad Ebingeraf1e9832020-10-14 10:49:28 -0700556 } finally {
557 Binder.restoreCallingIdentity(identity);
558 }
559 }
560
Brad Ebinger36221382020-12-09 00:33:39 +0000561 @Override
562 public void triggerNetworkRegistration(int subId, ISipDelegate connection, int sipCode,
563 String sipReason) {
Brad Ebinger4df7e242021-02-17 23:23:21 +0000564 enforceImsSingleRegistrationPermission("triggerNetworkRegistration");
Brad Ebinger36221382020-12-09 00:33:39 +0000565
566 final long identity = Binder.clearCallingIdentity();
567 try {
568 SipTransportController transport = getRcsFeatureController(subId).getFeature(
569 SipTransportController.class);
570 if (transport == null) {
571 return;
572 }
573 transport.triggerFullNetworkRegistration(subId, connection, sipCode, sipReason);
574 } finally {
575 Binder.restoreCallingIdentity(identity);
576 }
577 }
578
James.cf Linaf3183c2019-10-24 00:59:00 +0800579 /**
Brad Ebingere3ae65a2020-09-11 12:45:11 -0700580 * Registers for updates to the RcsFeature connection through the IImsServiceFeatureCallback
581 * callback.
582 */
583 @Override
Brad Ebinger6366ce92020-10-01 13:51:05 -0700584 public void registerRcsFeatureCallback(int slotId, IImsServiceFeatureCallback callback) {
Brad Ebingere3ae65a2020-09-11 12:45:11 -0700585 enforceModifyPermission();
586
587 final long identity = Binder.clearCallingIdentity();
588 try {
589 if (mImsResolver == null) {
590 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
591 "Device does not support IMS");
592 }
Brad Ebinger6366ce92020-10-01 13:51:05 -0700593 mImsResolver.listenForFeature(slotId, ImsFeature.FEATURE_RCS, callback);
Brad Ebingere3ae65a2020-09-11 12:45:11 -0700594 } finally {
595 Binder.restoreCallingIdentity(identity);
596 }
597 }
Brad Ebinger6366ce92020-10-01 13:51:05 -0700598
Brad Ebingere3ae65a2020-09-11 12:45:11 -0700599 /**
600 * Unregister a previously registered IImsServiceFeatureCallback associated with an ImsFeature.
601 */
602 @Override
603 public void unregisterImsFeatureCallback(IImsServiceFeatureCallback callback) {
604 enforceModifyPermission();
605
606 final long identity = Binder.clearCallingIdentity();
607 try {
608 if (mImsResolver == null) return;
609 mImsResolver.unregisterImsFeatureCallback(callback);
610 } finally {
611 Binder.restoreCallingIdentity(identity);
612 }
613 }
614
615 /**
James.cf Linaf3183c2019-10-24 00:59:00 +0800616 * Make sure either called from same process as self (phone) or IPC caller has read privilege.
617 *
618 * @throws SecurityException if the caller does not have the required permission
619 */
620 private void enforceReadPrivilegedPermission(String message) {
621 mApp.enforceCallingOrSelfPermission(
622 android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, message);
623 }
624
625 /**
Brad Ebinger4df7e242021-02-17 23:23:21 +0000626 * @throws SecurityException if the caller does not have the required
627 * PERFORM_IMS_SINGLE_REGISTRATION permission.
628 */
629 private void enforceImsSingleRegistrationPermission(String message) {
630 mApp.enforceCallingOrSelfPermission(
631 Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION, message);
632 }
633
634 /**
James.cf Linaf3183c2019-10-24 00:59:00 +0800635 * Make sure the caller has the MODIFY_PHONE_STATE permission.
636 *
637 * @throws SecurityException if the caller does not have the required permission
638 */
639 private void enforceModifyPermission() {
640 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE, null);
641 }
James.cf Lincad981c2019-12-10 20:37:56 +0800642
643 /**
James.cf Lin051dd252021-01-21 03:30:54 +0800644 * Make sure the caller has the ACCESS_RCS_USER_CAPABILITY_EXCHANGE permission.
645 *
646 * @throws SecurityException if the caller does not have the required permission.
647 */
648 private void enforceAccessUserCapabilityExchangePermission(String message) {
649 mApp.enforceCallingOrSelfPermission(
650 android.Manifest.permission.ACCESS_RCS_USER_CAPABILITY_EXCHANGE, message);
651 }
652
653 /**
654 * Make sure the caller has the READ_CONTACTS permission.
655 *
656 * @throws SecurityException if the caller does not have the required permission.
657 */
658 private void enforceReadContactsPermission(String message) {
659 mApp.enforceCallingOrSelfPermission(
660 android.Manifest.permission.READ_CONTACTS, message);
661 }
662
663 /**
James.cf Lindc2d5422019-12-31 14:40:25 +0800664 * Retrieve ImsPhone instance.
James.cf Lincad981c2019-12-10 20:37:56 +0800665 *
666 * @param subId the subscription ID
James.cf Lindc2d5422019-12-31 14:40:25 +0800667 * @return The ImsPhone instance
668 * @throws ServiceSpecificException if getting ImsPhone instance failed.
James.cf Lincad981c2019-12-10 20:37:56 +0800669 */
James.cf Lindc2d5422019-12-31 14:40:25 +0800670 private ImsPhone getImsPhone(int subId) {
671 if (!ImsManager.isImsSupportedOnDevice(mApp)) {
672 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
673 "IMS is not available on device.");
674 }
James.cf Lincad981c2019-12-10 20:37:56 +0800675 Phone phone = PhoneGlobals.getPhone(subId);
676 if (phone == null) {
677 throw new ServiceSpecificException(ImsException.CODE_ERROR_INVALID_SUBSCRIPTION,
678 "Invalid subscription Id: " + subId);
679 }
680 ImsPhone imsPhone = (ImsPhone) phone.getImsPhone();
681 if (imsPhone == null) {
James.cf Lindc2d5422019-12-31 14:40:25 +0800682 throw new ServiceSpecificException(ImsException.CODE_ERROR_SERVICE_UNAVAILABLE,
683 "Cannot find ImsPhone instance: " + subId);
684 }
685 return imsPhone;
686 }
687
688 /**
689 * Retrieve RcsFeatureManager instance.
690 *
691 * @param subId the subscription ID
692 * @return The RcsFeatureManager instance
693 * @throws ServiceSpecificException if getting RcsFeatureManager instance failed.
694 */
Brad Ebingera68a4972020-01-30 17:31:23 -0800695 private RcsFeatureController getRcsFeatureController(int subId) {
James.cf Lindc2d5422019-12-31 14:40:25 +0800696 if (!ImsManager.isImsSupportedOnDevice(mApp)) {
James.cf Lincad981c2019-12-10 20:37:56 +0800697 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
James.cf Lindc2d5422019-12-31 14:40:25 +0800698 "IMS is not available on device.");
699 }
Brad Ebingera68a4972020-01-30 17:31:23 -0800700 if (mRcsService == null) {
701 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
702 "IMS is not available on device.");
703 }
James.cf Lindc2d5422019-12-31 14:40:25 +0800704 Phone phone = PhoneGlobals.getPhone(subId);
705 if (phone == null) {
706 throw new ServiceSpecificException(ImsException.CODE_ERROR_INVALID_SUBSCRIPTION,
707 "Invalid subscription Id: " + subId);
708 }
Brad Ebingera68a4972020-01-30 17:31:23 -0800709 int slotId = phone.getPhoneId();
710 RcsFeatureController c = mRcsService.getFeatureController(slotId);
711 if (c == null) {
Brad Ebinger036dc9e2020-02-06 15:49:06 -0800712 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
713 "The requested operation is not supported for subId " + subId);
James.cf Lincad981c2019-12-10 20:37:56 +0800714 }
Brad Ebingera68a4972020-01-30 17:31:23 -0800715 return c;
James.cf Lincad981c2019-12-10 20:37:56 +0800716 }
James.cf Linc9f35a42020-01-15 02:35:22 +0800717
Brad Ebinger49a72b42021-01-29 00:55:24 +0000718 private boolean isImsSingleRegistrationSupportedOnDevice() {
719 return mSingleRegistrationOverride != null ? mSingleRegistrationOverride
720 : mApp.getPackageManager().hasSystemFeature(
721 PackageManager.FEATURE_TELEPHONY_IMS_SINGLE_REGISTRATION);
722 }
723
James.cf Linc9f35a42020-01-15 02:35:22 +0800724 void setRcsService(TelephonyRcsService rcsService) {
725 mRcsService = rcsService;
726 }
Brad Ebinger49a72b42021-01-29 00:55:24 +0000727
728 /**
729 * Override device RCS single registration support check for CTS testing or remove override
730 * if the Boolean is set to null.
731 */
732 void setDeviceSingleRegistrationSupportOverride(Boolean deviceOverrideValue) {
733 mSingleRegistrationOverride = deviceOverrideValue;
734 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800735}