blob: ad33302d12ee2cb62739711414eee2648f107b7a [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;
James.cf Lin051dd252021-01-21 03:30:54 +080020import android.app.ActivityManager;
Brad Ebinger63b6f5a2020-10-27 11:43:35 -070021import android.content.pm.PackageManager;
James.cf Linaf3183c2019-10-24 00:59:00 +080022import android.net.Uri;
James.cf Lincad981c2019-12-10 20:37:56 +080023import android.os.Binder;
24import android.os.RemoteException;
James.cf Lincad981c2019-12-10 20:37:56 +080025import android.os.ServiceSpecificException;
Brad Ebinger63b6f5a2020-10-27 11:43:35 -070026import android.os.UserHandle;
Brad Ebingerb7a866a2020-01-22 17:51:55 -080027import android.telephony.SubscriptionManager;
Peter Wangc035ce42020-01-08 21:00:22 -080028import android.telephony.TelephonyFrameworkInitializer;
Brad Ebingeraf1e9832020-10-14 10:49:28 -070029import android.telephony.ims.DelegateRequest;
James.cf Lincad981c2019-12-10 20:37:56 +080030import android.telephony.ims.ImsException;
Brad Ebingerd4c5bde2021-02-12 06:18:28 +000031import android.telephony.ims.RcsContactUceCapability;
James.cf Lin99a360d2020-11-04 10:48:37 +080032import android.telephony.ims.RcsUceAdapter.PublishState;
James.cf Lindc2d5422019-12-31 14:40:25 +080033import android.telephony.ims.RegistrationManager;
James.cf Linaf3183c2019-10-24 00:59:00 +080034import android.telephony.ims.aidl.IImsCapabilityCallback;
35import android.telephony.ims.aidl.IImsRcsController;
James.cf Lindc2d5422019-12-31 14:40:25 +080036import android.telephony.ims.aidl.IImsRegistrationCallback;
James.cf Linaf3183c2019-10-24 00:59:00 +080037import android.telephony.ims.aidl.IRcsUceControllerCallback;
James.cf Lincdad3862020-02-25 15:55:03 +080038import android.telephony.ims.aidl.IRcsUcePublishStateCallback;
Brad Ebingeraf1e9832020-10-14 10:49:28 -070039import android.telephony.ims.aidl.ISipDelegate;
40import android.telephony.ims.aidl.ISipDelegateConnectionStateCallback;
41import android.telephony.ims.aidl.ISipDelegateMessageCallback;
Brad Ebingere3ae65a2020-09-11 12:45:11 -070042import android.telephony.ims.feature.ImsFeature;
James.cf Linaf3183c2019-10-24 00:59:00 +080043import android.telephony.ims.feature.RcsFeature;
James.cf Lincad981c2019-12-10 20:37:56 +080044import android.telephony.ims.stub.ImsRegistrationImplBase;
James.cf Linaf3183c2019-10-24 00:59:00 +080045import android.util.Log;
46
James.cf Lindc2d5422019-12-31 14:40:25 +080047import com.android.ims.ImsManager;
Brad Ebingere3ae65a2020-09-11 12:45:11 -070048import com.android.ims.internal.IImsServiceFeatureCallback;
James.cf Lindc2d5422019-12-31 14:40:25 +080049import com.android.internal.telephony.IIntegerConsumer;
James.cf Lincad981c2019-12-10 20:37:56 +080050import com.android.internal.telephony.Phone;
Brad Ebinger8b79edc2020-02-27 19:13:24 -080051import com.android.internal.telephony.TelephonyPermissions;
Brad Ebingere3ae65a2020-09-11 12:45:11 -070052import com.android.internal.telephony.ims.ImsResolver;
James.cf Lincad981c2019-12-10 20:37:56 +080053import com.android.internal.telephony.imsphone.ImsPhone;
Brad Ebingera68a4972020-01-30 17:31:23 -080054import com.android.services.telephony.rcs.RcsFeatureController;
Brad Ebingerb989c7c2020-09-23 17:03:48 -070055import com.android.services.telephony.rcs.SipTransportController;
James.cf Linc9f35a42020-01-15 02:35:22 +080056import com.android.services.telephony.rcs.TelephonyRcsService;
James.cf Lin99a360d2020-11-04 10:48:37 +080057import com.android.services.telephony.rcs.UceControllerManager;
James.cf Lincad981c2019-12-10 20:37:56 +080058
James.cf Linaf3183c2019-10-24 00:59:00 +080059import java.util.List;
Brad Ebingerd4c5bde2021-02-12 06:18:28 +000060import java.util.Set;
James.cf Linaf3183c2019-10-24 00:59:00 +080061
62/**
63 * Implementation of the IImsRcsController interface.
64 */
65public class ImsRcsController extends IImsRcsController.Stub {
66 private static final String TAG = "ImsRcsController";
67
68 /** The singleton instance. */
69 private static ImsRcsController sInstance;
70
71 private PhoneGlobals mApp;
James.cf Linc9f35a42020-01-15 02:35:22 +080072 private TelephonyRcsService mRcsService;
Brad Ebingere3ae65a2020-09-11 12:45:11 -070073 private ImsResolver mImsResolver;
Brad Ebinger49a72b42021-01-29 00:55:24 +000074 // set by shell cmd phone src set-device-enabled true/false
75 private Boolean mSingleRegistrationOverride;
James.cf Linaf3183c2019-10-24 00:59:00 +080076
77 /**
78 * Initialize the singleton ImsRcsController instance.
79 * This is only done once, at startup, from PhoneApp.onCreate().
80 */
81 static ImsRcsController init(PhoneGlobals app) {
82 synchronized (ImsRcsController.class) {
83 if (sInstance == null) {
84 sInstance = new ImsRcsController(app);
85 } else {
86 Log.wtf(TAG, "init() called multiple times! sInstance = " + sInstance);
87 }
88 return sInstance;
89 }
90 }
91
92 /** Private constructor; @see init() */
93 private ImsRcsController(PhoneGlobals app) {
94 Log.i(TAG, "ImsRcsController");
95 mApp = app;
Peter Wangc035ce42020-01-08 21:00:22 -080096 TelephonyFrameworkInitializer
97 .getTelephonyServiceManager().getTelephonyImsServiceRegisterer().register(this);
Brad Ebingere3ae65a2020-09-11 12:45:11 -070098 mImsResolver = mApp.getImsResolver();
James.cf Linaf3183c2019-10-24 00:59:00 +080099 }
100
James.cf Lincad981c2019-12-10 20:37:56 +0800101 /**
Brad Ebingera68a4972020-01-30 17:31:23 -0800102 * Register a {@link RegistrationManager.RegistrationCallback} to receive IMS network
103 * registration state.
James.cf Lindc2d5422019-12-31 14:40:25 +0800104 */
105 @Override
Brad Ebingera68a4972020-01-30 17:31:23 -0800106 public void registerImsRegistrationCallback(int subId, IImsRegistrationCallback callback) {
James.cf Linf020d162021-01-31 22:15:52 +0800107 TelephonyPermissions.enforeceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
108 mApp, subId, "registerImsRegistrationCallback");
James.cf Lindc2d5422019-12-31 14:40:25 +0800109 final long token = Binder.clearCallingIdentity();
110 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800111 getRcsFeatureController(subId).registerImsRegistrationCallback(subId, callback);
112 } catch (ImsException e) {
James.cf Lindc2d5422019-12-31 14:40:25 +0800113 Log.e(TAG, "registerImsRegistrationCallback: sudId=" + subId + ", " + e.getMessage());
114 throw new ServiceSpecificException(e.getCode());
115 } finally {
116 Binder.restoreCallingIdentity(token);
117 }
118 }
119
120 /**
Brad Ebingera68a4972020-01-30 17:31:23 -0800121 * Removes an existing {@link RegistrationManager.RegistrationCallback}.
James.cf Lindc2d5422019-12-31 14:40:25 +0800122 */
123 @Override
124 public void unregisterImsRegistrationCallback(int subId, IImsRegistrationCallback callback) {
James.cf Linf020d162021-01-31 22:15:52 +0800125 TelephonyPermissions.enforeceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
126 mApp, subId, "unregisterImsRegistrationCallback");
James.cf Lindc2d5422019-12-31 14:40:25 +0800127 final long token = Binder.clearCallingIdentity();
128 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800129 getRcsFeatureController(subId).unregisterImsRegistrationCallback(subId, callback);
James.cf Lindc2d5422019-12-31 14:40:25 +0800130 } catch (ServiceSpecificException e) {
131 Log.e(TAG, "unregisterImsRegistrationCallback: error=" + e.errorCode);
132 } finally {
133 Binder.restoreCallingIdentity(token);
134 }
135 }
136
137 /**
138 * Get the IMS service registration state for the RcsFeature associated with this sub id.
139 */
140 @Override
141 public void getImsRcsRegistrationState(int subId, IIntegerConsumer consumer) {
James.cf Linf020d162021-01-31 22:15:52 +0800142 TelephonyPermissions.enforeceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
143 mApp, subId, "getImsRcsRegistrationState");
James.cf Lindc2d5422019-12-31 14:40:25 +0800144 final long token = Binder.clearCallingIdentity();
145 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800146 getRcsFeatureController(subId).getRegistrationState(regState -> {
James.cf Lindc2d5422019-12-31 14:40:25 +0800147 try {
148 consumer.accept((regState == null)
149 ? RegistrationManager.REGISTRATION_STATE_NOT_REGISTERED : regState);
150 } catch (RemoteException e) {
151 Log.w(TAG, "getImsRcsRegistrationState: callback is not available.");
152 }
153 });
154 } finally {
155 Binder.restoreCallingIdentity(token);
156 }
157 }
158
159 /**
160 * Gets the Transport Type associated with the current IMS RCS registration.
161 */
162 @Override
163 public void getImsRcsRegistrationTransportType(int subId, IIntegerConsumer consumer) {
James.cf Linf020d162021-01-31 22:15:52 +0800164 TelephonyPermissions.enforeceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
165 mApp, subId, "getImsRcsRegistrationTransportType");
James.cf Lindc2d5422019-12-31 14:40:25 +0800166 final long token = Binder.clearCallingIdentity();
167 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800168 getRcsFeatureController(subId).getRegistrationTech(regTech -> {
James.cf Lindc2d5422019-12-31 14:40:25 +0800169 // Convert registration tech from ImsRegistrationImplBase -> RegistrationManager
170 int regTechConverted = (regTech == null)
171 ? ImsRegistrationImplBase.REGISTRATION_TECH_NONE : regTech;
172 regTechConverted = RegistrationManager.IMS_REG_TO_ACCESS_TYPE_MAP.get(
173 regTechConverted);
174 try {
175 consumer.accept(regTechConverted);
176 } catch (RemoteException e) {
177 Log.w(TAG, "getImsRcsRegistrationTransportType: callback is not available.");
178 }
179 });
180 } finally {
181 Binder.restoreCallingIdentity(token);
182 }
183 }
184
185 /**
James.cf Lincad981c2019-12-10 20:37:56 +0800186 * Register a capability callback which will provide RCS availability updates for the
187 * subscription specified.
188 *
189 * @param subId the subscription ID
190 * @param callback The ImsCapabilityCallback to be registered.
191 */
James.cf Linaf3183c2019-10-24 00:59:00 +0800192 @Override
Brad Ebingera68a4972020-01-30 17:31:23 -0800193 public void registerRcsAvailabilityCallback(int subId, IImsCapabilityCallback callback) {
James.cf Linaf3183c2019-10-24 00:59:00 +0800194 enforceReadPrivilegedPermission("registerRcsAvailabilityCallback");
James.cf Lincad981c2019-12-10 20:37:56 +0800195 final long token = Binder.clearCallingIdentity();
196 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800197 getRcsFeatureController(subId).registerRcsAvailabilityCallback(subId, callback);
198 } catch (ImsException e) {
James.cf Lincad981c2019-12-10 20:37:56 +0800199 Log.e(TAG, "registerRcsAvailabilityCallback: sudId=" + subId + ", " + e.getMessage());
200 throw new ServiceSpecificException(e.getCode());
201 } finally {
202 Binder.restoreCallingIdentity(token);
203 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800204 }
205
James.cf Lincad981c2019-12-10 20:37:56 +0800206 /**
207 * Remove the registered capability callback.
208 *
209 * @param subId the subscription ID
210 * @param callback The ImsCapabilityCallback to be removed.
211 */
James.cf Linaf3183c2019-10-24 00:59:00 +0800212 @Override
James.cf Lincad981c2019-12-10 20:37:56 +0800213 public void unregisterRcsAvailabilityCallback(int subId, IImsCapabilityCallback callback) {
James.cf Linaf3183c2019-10-24 00:59:00 +0800214 enforceReadPrivilegedPermission("unregisterRcsAvailabilityCallback");
James.cf Lincad981c2019-12-10 20:37:56 +0800215 final long token = Binder.clearCallingIdentity();
216 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800217 getRcsFeatureController(subId).unregisterRcsAvailabilityCallback(subId, callback);
James.cf Lincad981c2019-12-10 20:37:56 +0800218 } finally {
219 Binder.restoreCallingIdentity(token);
220 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800221 }
222
James.cf Lincad981c2019-12-10 20:37:56 +0800223 /**
224 * Query for the capability of an IMS RCS service
225 *
226 * @param subId the subscription ID
227 * @param capability the RCS capability to query.
James.cf Linf020d162021-01-31 22:15:52 +0800228 * @param radioTech the radio technology type that we are querying.
James.cf Lincad981c2019-12-10 20:37:56 +0800229 * @return true if the RCS capability is capable for this subscription, false otherwise.
230 */
James.cf Linaf3183c2019-10-24 00:59:00 +0800231 @Override
232 public boolean isCapable(int subId,
James.cf Lincad981c2019-12-10 20:37:56 +0800233 @RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability,
234 @ImsRegistrationImplBase.ImsRegistrationTech int radioTech) {
James.cf Linaf3183c2019-10-24 00:59:00 +0800235 enforceReadPrivilegedPermission("isCapable");
James.cf Lincad981c2019-12-10 20:37:56 +0800236 final long token = Binder.clearCallingIdentity();
237 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800238 return getRcsFeatureController(subId).isCapable(capability, radioTech);
239 } catch (ImsException e) {
James.cf Lincad981c2019-12-10 20:37:56 +0800240 Log.e(TAG, "isCapable: sudId=" + subId
241 + ", capability=" + capability + ", " + e.getMessage());
242 return false;
243 } finally {
244 Binder.restoreCallingIdentity(token);
245 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800246 }
247
James.cf Lincad981c2019-12-10 20:37:56 +0800248 /**
249 * Query the availability of an IMS RCS capability.
250 *
251 * @param subId the subscription ID
252 * @param capability the RCS capability to query.
253 * @return true if the RCS capability is currently available for the associated subscription,
James.cf Linf020d162021-01-31 22:15:52 +0800254 * @param radioTech the radio technology type that we are querying.
James.cf Lincad981c2019-12-10 20:37:56 +0800255 * false otherwise.
256 */
James.cf Linaf3183c2019-10-24 00:59:00 +0800257 @Override
258 public boolean isAvailable(int subId,
James.cf Linf020d162021-01-31 22:15:52 +0800259 @RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability,
260 @ImsRegistrationImplBase.ImsRegistrationTech int radioTech) {
James.cf Linaf3183c2019-10-24 00:59:00 +0800261 enforceReadPrivilegedPermission("isAvailable");
James.cf Lincad981c2019-12-10 20:37:56 +0800262 final long token = Binder.clearCallingIdentity();
263 try {
James.cf Linf020d162021-01-31 22:15:52 +0800264 return getRcsFeatureController(subId).isAvailable(capability, radioTech);
Brad Ebingera68a4972020-01-30 17:31:23 -0800265 } catch (ImsException e) {
James.cf Lincad981c2019-12-10 20:37:56 +0800266 Log.e(TAG, "isAvailable: sudId=" + subId
267 + ", capability=" + capability + ", " + e.getMessage());
268 return false;
269 } finally {
270 Binder.restoreCallingIdentity(token);
271 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800272 }
273
274 @Override
Brad Ebinger8b79edc2020-02-27 19:13:24 -0800275 public void requestCapabilities(int subId, String callingPackage, String callingFeatureId,
276 List<Uri> contactNumbers, IRcsUceControllerCallback c) {
James.cf Lin051dd252021-01-21 03:30:54 +0800277 enforceAccessUserCapabilityExchangePermission("requestCapabilities");
278 enforceReadContactsPermission("requestCapabilities");
279 if (!isCallingProcessInForeground(Binder.getCallingUid())) {
280 throw new SecurityException("The caller is not in the foreground.");
281 }
Brad Ebingera68a4972020-01-30 17:31:23 -0800282 final long token = Binder.clearCallingIdentity();
283 try {
James.cf Lin99a360d2020-11-04 10:48:37 +0800284 UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
285 UceControllerManager.class);
286 if (uceCtrlManager == null) {
Brad Ebingera68a4972020-01-30 17:31:23 -0800287 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
288 "This subscription does not support UCE.");
289 }
James.cf Lin99a360d2020-11-04 10:48:37 +0800290 uceCtrlManager.requestCapabilities(contactNumbers, c);
291 } catch (ImsException e) {
292 throw new ServiceSpecificException(e.getCode(), e.getMessage());
Brad Ebingera68a4972020-01-30 17:31:23 -0800293 } finally {
294 Binder.restoreCallingIdentity(token);
Brad Ebinger1aa94992020-01-22 14:17:23 -0800295 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800296 }
297
298 @Override
James.cf Linbcdf8b32021-01-14 16:44:13 +0800299 public void requestAvailability(int subId, String callingPackage,
James.cf Lin64e91212020-10-30 01:09:52 +0800300 String callingFeatureId, Uri contactNumber, IRcsUceControllerCallback c) {
James.cf Lin051dd252021-01-21 03:30:54 +0800301 enforceAccessUserCapabilityExchangePermission("requestAvailability");
302 enforceReadContactsPermission("requestAvailability");
303 if (!isCallingProcessInForeground(Binder.getCallingUid())) {
304 throw new SecurityException("The caller is not in the foreground.");
305 }
Brad Ebingera68a4972020-01-30 17:31:23 -0800306 final long token = Binder.clearCallingIdentity();
307 try {
James.cf Lin99a360d2020-11-04 10:48:37 +0800308 UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
309 UceControllerManager.class);
310 if (uceCtrlManager == null) {
Brad Ebingera68a4972020-01-30 17:31:23 -0800311 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
312 "This subscription does not support UCE.");
313 }
James.cf Lin99a360d2020-11-04 10:48:37 +0800314 uceCtrlManager.requestNetworkAvailability(contactNumber, c);
315 } catch (ImsException e) {
316 throw new ServiceSpecificException(e.getCode(), e.getMessage());
317 } finally {
318 Binder.restoreCallingIdentity(token);
319 }
320 }
321
322 @Override
323 public @PublishState int getUcePublishState(int subId) {
324 enforceReadPrivilegedPermission("getUcePublishState");
325 final long token = Binder.clearCallingIdentity();
326 try {
327 UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
328 UceControllerManager.class);
329 if (uceCtrlManager == null) {
330 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
331 "This subscription does not support UCE.");
332 }
333 return uceCtrlManager.getUcePublishState();
334 } catch (ImsException e) {
335 throw new ServiceSpecificException(e.getCode(), e.getMessage());
336 } finally {
337 Binder.restoreCallingIdentity(token);
338 }
339 }
340
Brad Ebingerd4c5bde2021-02-12 06:18:28 +0000341 /**
342 * Add new feature tags to the Set used to calculate the capabilities in PUBLISH.
343 */
344 // Used for SHELL command only right now.
345 public RcsContactUceCapability addUceRegistrationOverrideShell(int subId,
346 Set<String> featureTags) throws ImsException {
347 // Permission check happening in PhoneInterfaceManager.
348 UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
349 UceControllerManager.class);
350 if (uceCtrlManager == null) {
351 return null;
352 }
353 return uceCtrlManager.addUceRegistrationOverride(featureTags);
354 }
355
356 /**
357 * Remove existing feature tags to the Set used to calculate the capabilities in PUBLISH.
358 */
359 // Used for SHELL command only right now.
360 public RcsContactUceCapability removeUceRegistrationOverrideShell(int subId,
361 Set<String> featureTags) throws ImsException {
362 // Permission check happening in PhoneInterfaceManager.
363 UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
364 UceControllerManager.class);
365 if (uceCtrlManager == null) {
366 return null;
367 }
368 return uceCtrlManager.removeUceRegistrationOverride(featureTags);
369 }
370
371 /**
372 * Clear all overrides in the Set used to calculate the capabilities in PUBLISH.
373 */
374 // Used for SHELL command only right now.
375 public RcsContactUceCapability clearUceRegistrationOverrideShell(int subId)
376 throws ImsException {
377 // Permission check happening in PhoneInterfaceManager.
378 UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
379 UceControllerManager.class);
380 if (uceCtrlManager == null) {
381 return null;
382 }
383 return uceCtrlManager.clearUceRegistrationOverride();
384 }
385
386 /**
387 * @return current RcsContactUceCapability instance that will be used for PUBLISH.
388 */
389 // Used for SHELL command only right now.
390 public RcsContactUceCapability getLatestRcsContactUceCapabilityShell(int subId)
391 throws ImsException {
392 // Permission check happening in PhoneInterfaceManager.
393 UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
394 UceControllerManager.class);
395 if (uceCtrlManager == null) {
396 return null;
397 }
398 return uceCtrlManager.getLatestRcsContactUceCapability();
399 }
400
401 /**
402 * @return the PIDf XML used in the last PUBLISH procedure or "none" if the device is not
403 * published. Returns {@code null} if the operation failed due to an error.
404 */
405 // Used for SHELL command only right now.
406 public String getLastUcePidfXmlShell(int subId) throws ImsException {
407 // Permission check happening in PhoneInterfaceManager.
408 UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
409 UceControllerManager.class);
410 if (uceCtrlManager == null) {
411 return null;
412 }
413 String pidfXml = uceCtrlManager.getLastPidfXml();
414 return pidfXml == null ? "none" : pidfXml;
415 }
416
James.cf Lin99a360d2020-11-04 10:48:37 +0800417 @Override
418 public void registerUcePublishStateCallback(int subId, IRcsUcePublishStateCallback c) {
419 enforceReadPrivilegedPermission("registerUcePublishStateCallback");
420 final long token = Binder.clearCallingIdentity();
421 try {
422 UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
423 UceControllerManager.class);
424 if (uceCtrlManager == null) {
425 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
426 "This subscription does not support UCE.");
427 }
428 uceCtrlManager.registerPublishStateCallback(c);
429 } catch (ImsException e) {
430 throw new ServiceSpecificException(e.getCode(), e.getMessage());
431 } finally {
432 Binder.restoreCallingIdentity(token);
433 }
434 }
435
436 @Override
437 public void unregisterUcePublishStateCallback(int subId, IRcsUcePublishStateCallback c) {
438 enforceReadPrivilegedPermission("unregisterUcePublishStateCallback");
439 final long token = Binder.clearCallingIdentity();
440 try {
441 UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
442 UceControllerManager.class);
443 if (uceCtrlManager == null) {
444 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
445 "This subscription does not support UCE.");
446 }
447 uceCtrlManager.unregisterPublishStateCallback(c);
Brad Ebingera68a4972020-01-30 17:31:23 -0800448 } finally {
449 Binder.restoreCallingIdentity(token);
Brad Ebinger1aa94992020-01-22 14:17:23 -0800450 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800451 }
452
453 @Override
Brad Ebinger8b79edc2020-02-27 19:13:24 -0800454 public boolean isUceSettingEnabled(int subId, String callingPackage, String callingFeatureId) {
455 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
456 mApp, subId, callingPackage, callingFeatureId, "isUceSettingEnabled")) {
457 Log.w(TAG, "isUceSettingEnabled: READ_PHONE_STATE app op disabled when accessing "
458 + "isUceSettingEnabled");
459 return false;
460 }
461 final long token = Binder.clearCallingIdentity();
462 try {
463 return SubscriptionManager.getBooleanSubscriptionProperty(subId,
464 SubscriptionManager.IMS_RCS_UCE_ENABLED, false /*defaultValue*/, mApp);
465 } finally {
466 Binder.restoreCallingIdentity(token);
467 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800468 }
469
470 @Override
471 public void setUceSettingEnabled(int subId, boolean isEnabled) {
472 enforceModifyPermission();
Brad Ebinger8b79edc2020-02-27 19:13:24 -0800473 final long token = Binder.clearCallingIdentity();
474 try {
475 SubscriptionManager.setSubscriptionProperty(subId,
476 SubscriptionManager.IMS_RCS_UCE_ENABLED, (isEnabled ? "1" : "0"));
477 } finally {
478 Binder.restoreCallingIdentity(token);
479 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800480 }
481
Brad Ebingerb989c7c2020-09-23 17:03:48 -0700482 @Override
483 public boolean isSipDelegateSupported(int subId) {
Brad Ebinger4df7e242021-02-17 23:23:21 +0000484 TelephonyPermissions.enforceAnyPermissionGranted(mApp, Binder.getCallingUid(),
485 "isSipDelegateSupported",
486 Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION,
487 Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
Brad Ebinger49a72b42021-01-29 00:55:24 +0000488 if (!isImsSingleRegistrationSupportedOnDevice()) {
489 return false;
490 }
Brad Ebingerb989c7c2020-09-23 17:03:48 -0700491 final long token = Binder.clearCallingIdentity();
492 try {
493 SipTransportController transport = getRcsFeatureController(subId).getFeature(
494 SipTransportController.class);
495 if (transport == null) {
496 return false;
497 }
498 return transport.isSupported(subId);
499 } catch (ImsException e) {
500 throw new ServiceSpecificException(e.getCode(), e.getMessage());
501 } catch (ServiceSpecificException e) {
502 if (e.errorCode == ImsException.CODE_ERROR_UNSUPPORTED_OPERATION) {
503 return false;
504 }
505 throw e;
506 } finally {
507 Binder.restoreCallingIdentity(token);
508 }
509 }
510
Brad Ebingeraf1e9832020-10-14 10:49:28 -0700511 @Override
Brad Ebinger63b6f5a2020-10-27 11:43:35 -0700512 public void createSipDelegate(int subId, DelegateRequest request, String packageName,
Brad Ebingeraf1e9832020-10-14 10:49:28 -0700513 ISipDelegateConnectionStateCallback delegateState,
514 ISipDelegateMessageCallback delegateMessage) {
Brad Ebinger4df7e242021-02-17 23:23:21 +0000515 enforceImsSingleRegistrationPermission("createSipDelegate");
Brad Ebinger49a72b42021-01-29 00:55:24 +0000516 if (!isImsSingleRegistrationSupportedOnDevice()) {
517 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
518 "SipDelegate creation is only supported for devices supporting IMS single "
519 + "registration");
520 }
Brad Ebinger63b6f5a2020-10-27 11:43:35 -0700521 if (!UserHandle.getUserHandleForUid(Binder.getCallingUid()).isSystem()) {
522 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
523 "SipDelegate creation is only available to primary user.");
524 }
525 try {
526 int remoteUid = mApp.getPackageManager().getPackageUid(packageName, 0 /*flags*/);
527 if (Binder.getCallingUid() != remoteUid) {
528 throw new SecurityException("passed in packageName does not match the caller");
529 }
530 } catch (PackageManager.NameNotFoundException e) {
531 throw new SecurityException("Passed in PackageName can not be found on device");
532 }
Brad Ebingeraf1e9832020-10-14 10:49:28 -0700533
534 final long identity = Binder.clearCallingIdentity();
535 SipTransportController transport = getRcsFeatureController(subId).getFeature(
536 SipTransportController.class);
537 if (transport == null) {
538 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
539 "This subscription does not support the creation of SIP delegates");
540 }
541 try {
Brad Ebinger63b6f5a2020-10-27 11:43:35 -0700542 transport.createSipDelegate(subId, request, packageName, delegateState,
543 delegateMessage);
Brad Ebingeraf1e9832020-10-14 10:49:28 -0700544 } catch (ImsException e) {
545 throw new ServiceSpecificException(e.getCode(), e.getMessage());
546 } finally {
547 Binder.restoreCallingIdentity(identity);
548 }
549 }
550
551 @Override
552 public void destroySipDelegate(int subId, ISipDelegate connection, int reason) {
Brad Ebinger4df7e242021-02-17 23:23:21 +0000553 enforceImsSingleRegistrationPermission("destroySipDelegate");
Brad Ebingeraf1e9832020-10-14 10:49:28 -0700554
555 final long identity = Binder.clearCallingIdentity();
556 try {
Brad Ebinger63b6f5a2020-10-27 11:43:35 -0700557 SipTransportController transport = getRcsFeatureController(subId).getFeature(
558 SipTransportController.class);
559 if (transport == null) {
560 return;
561 }
562 transport.destroySipDelegate(subId, connection, reason);
Brad Ebingeraf1e9832020-10-14 10:49:28 -0700563 } finally {
564 Binder.restoreCallingIdentity(identity);
565 }
566 }
567
Brad Ebinger36221382020-12-09 00:33:39 +0000568 @Override
569 public void triggerNetworkRegistration(int subId, ISipDelegate connection, int sipCode,
570 String sipReason) {
Brad Ebinger4df7e242021-02-17 23:23:21 +0000571 enforceImsSingleRegistrationPermission("triggerNetworkRegistration");
Brad Ebinger36221382020-12-09 00:33:39 +0000572
573 final long identity = Binder.clearCallingIdentity();
574 try {
575 SipTransportController transport = getRcsFeatureController(subId).getFeature(
576 SipTransportController.class);
577 if (transport == null) {
578 return;
579 }
580 transport.triggerFullNetworkRegistration(subId, connection, sipCode, sipReason);
581 } finally {
582 Binder.restoreCallingIdentity(identity);
583 }
584 }
585
James.cf Linaf3183c2019-10-24 00:59:00 +0800586 /**
Brad Ebingere3ae65a2020-09-11 12:45:11 -0700587 * Registers for updates to the RcsFeature connection through the IImsServiceFeatureCallback
588 * callback.
589 */
590 @Override
Brad Ebinger6366ce92020-10-01 13:51:05 -0700591 public void registerRcsFeatureCallback(int slotId, IImsServiceFeatureCallback callback) {
Brad Ebingere3ae65a2020-09-11 12:45:11 -0700592 enforceModifyPermission();
593
594 final long identity = Binder.clearCallingIdentity();
595 try {
596 if (mImsResolver == null) {
597 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
598 "Device does not support IMS");
599 }
Brad Ebinger6366ce92020-10-01 13:51:05 -0700600 mImsResolver.listenForFeature(slotId, ImsFeature.FEATURE_RCS, callback);
Brad Ebingere3ae65a2020-09-11 12:45:11 -0700601 } finally {
602 Binder.restoreCallingIdentity(identity);
603 }
604 }
Brad Ebinger6366ce92020-10-01 13:51:05 -0700605
Brad Ebingere3ae65a2020-09-11 12:45:11 -0700606 /**
607 * Unregister a previously registered IImsServiceFeatureCallback associated with an ImsFeature.
608 */
609 @Override
610 public void unregisterImsFeatureCallback(IImsServiceFeatureCallback callback) {
611 enforceModifyPermission();
612
613 final long identity = Binder.clearCallingIdentity();
614 try {
615 if (mImsResolver == null) return;
616 mImsResolver.unregisterImsFeatureCallback(callback);
617 } finally {
618 Binder.restoreCallingIdentity(identity);
619 }
620 }
621
622 /**
James.cf Linaf3183c2019-10-24 00:59:00 +0800623 * Make sure either called from same process as self (phone) or IPC caller has read privilege.
624 *
625 * @throws SecurityException if the caller does not have the required permission
626 */
627 private void enforceReadPrivilegedPermission(String message) {
628 mApp.enforceCallingOrSelfPermission(
629 android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, message);
630 }
631
632 /**
Brad Ebinger4df7e242021-02-17 23:23:21 +0000633 * @throws SecurityException if the caller does not have the required
634 * PERFORM_IMS_SINGLE_REGISTRATION permission.
635 */
636 private void enforceImsSingleRegistrationPermission(String message) {
637 mApp.enforceCallingOrSelfPermission(
638 Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION, message);
639 }
640
641 /**
James.cf Linaf3183c2019-10-24 00:59:00 +0800642 * Make sure the caller has the MODIFY_PHONE_STATE permission.
643 *
644 * @throws SecurityException if the caller does not have the required permission
645 */
646 private void enforceModifyPermission() {
647 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE, null);
648 }
James.cf Lincad981c2019-12-10 20:37:56 +0800649
650 /**
James.cf Lin051dd252021-01-21 03:30:54 +0800651 * Make sure the caller has the ACCESS_RCS_USER_CAPABILITY_EXCHANGE permission.
652 *
653 * @throws SecurityException if the caller does not have the required permission.
654 */
655 private void enforceAccessUserCapabilityExchangePermission(String message) {
656 mApp.enforceCallingOrSelfPermission(
657 android.Manifest.permission.ACCESS_RCS_USER_CAPABILITY_EXCHANGE, message);
658 }
659
660 /**
661 * Make sure the caller has the READ_CONTACTS permission.
662 *
663 * @throws SecurityException if the caller does not have the required permission.
664 */
665 private void enforceReadContactsPermission(String message) {
666 mApp.enforceCallingOrSelfPermission(
667 android.Manifest.permission.READ_CONTACTS, message);
668 }
669
670 /**
671 * Check if the calling process is in the foreground.
672 *
673 * @return true if the caller is in the foreground.
674 */
675 private boolean isCallingProcessInForeground(int uid) {
676 ActivityManager am = mApp.getSystemService(ActivityManager.class);
677 boolean isCallingProcessForeground = am != null
678 && am.getUidImportance(uid)
679 == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
680 return isCallingProcessForeground;
681 }
682
683 /**
James.cf Lindc2d5422019-12-31 14:40:25 +0800684 * Retrieve ImsPhone instance.
James.cf Lincad981c2019-12-10 20:37:56 +0800685 *
686 * @param subId the subscription ID
James.cf Lindc2d5422019-12-31 14:40:25 +0800687 * @return The ImsPhone instance
688 * @throws ServiceSpecificException if getting ImsPhone instance failed.
James.cf Lincad981c2019-12-10 20:37:56 +0800689 */
James.cf Lindc2d5422019-12-31 14:40:25 +0800690 private ImsPhone getImsPhone(int subId) {
691 if (!ImsManager.isImsSupportedOnDevice(mApp)) {
692 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
693 "IMS is not available on device.");
694 }
James.cf Lincad981c2019-12-10 20:37:56 +0800695 Phone phone = PhoneGlobals.getPhone(subId);
696 if (phone == null) {
697 throw new ServiceSpecificException(ImsException.CODE_ERROR_INVALID_SUBSCRIPTION,
698 "Invalid subscription Id: " + subId);
699 }
700 ImsPhone imsPhone = (ImsPhone) phone.getImsPhone();
701 if (imsPhone == null) {
James.cf Lindc2d5422019-12-31 14:40:25 +0800702 throw new ServiceSpecificException(ImsException.CODE_ERROR_SERVICE_UNAVAILABLE,
703 "Cannot find ImsPhone instance: " + subId);
704 }
705 return imsPhone;
706 }
707
708 /**
709 * Retrieve RcsFeatureManager instance.
710 *
711 * @param subId the subscription ID
712 * @return The RcsFeatureManager instance
713 * @throws ServiceSpecificException if getting RcsFeatureManager instance failed.
714 */
Brad Ebingera68a4972020-01-30 17:31:23 -0800715 private RcsFeatureController getRcsFeatureController(int subId) {
James.cf Lindc2d5422019-12-31 14:40:25 +0800716 if (!ImsManager.isImsSupportedOnDevice(mApp)) {
James.cf Lincad981c2019-12-10 20:37:56 +0800717 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
James.cf Lindc2d5422019-12-31 14:40:25 +0800718 "IMS is not available on device.");
719 }
Brad Ebingera68a4972020-01-30 17:31:23 -0800720 if (mRcsService == null) {
721 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
722 "IMS is not available on device.");
723 }
James.cf Lindc2d5422019-12-31 14:40:25 +0800724 Phone phone = PhoneGlobals.getPhone(subId);
725 if (phone == null) {
726 throw new ServiceSpecificException(ImsException.CODE_ERROR_INVALID_SUBSCRIPTION,
727 "Invalid subscription Id: " + subId);
728 }
Brad Ebingera68a4972020-01-30 17:31:23 -0800729 int slotId = phone.getPhoneId();
730 RcsFeatureController c = mRcsService.getFeatureController(slotId);
731 if (c == null) {
Brad Ebinger036dc9e2020-02-06 15:49:06 -0800732 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
733 "The requested operation is not supported for subId " + subId);
James.cf Lincad981c2019-12-10 20:37:56 +0800734 }
Brad Ebingera68a4972020-01-30 17:31:23 -0800735 return c;
James.cf Lincad981c2019-12-10 20:37:56 +0800736 }
James.cf Linc9f35a42020-01-15 02:35:22 +0800737
Brad Ebinger49a72b42021-01-29 00:55:24 +0000738 private boolean isImsSingleRegistrationSupportedOnDevice() {
739 return mSingleRegistrationOverride != null ? mSingleRegistrationOverride
740 : mApp.getPackageManager().hasSystemFeature(
741 PackageManager.FEATURE_TELEPHONY_IMS_SINGLE_REGISTRATION);
742 }
743
James.cf Linc9f35a42020-01-15 02:35:22 +0800744 void setRcsService(TelephonyRcsService rcsService) {
745 mRcsService = rcsService;
746 }
Brad Ebinger49a72b42021-01-29 00:55:24 +0000747
748 /**
749 * Override device RCS single registration support check for CTS testing or remove override
750 * if the Boolean is set to null.
751 */
752 void setDeviceSingleRegistrationSupportOverride(Boolean deviceOverrideValue) {
753 mSingleRegistrationOverride = deviceOverrideValue;
754 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800755}