blob: 3618d58aabf5dd732014499c5921d1ab3217dc81 [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;
Brad Ebingera68a4972020-01-30 17:31:23 -080052import com.android.services.telephony.rcs.RcsFeatureController;
Brad Ebingerb989c7c2020-09-23 17:03:48 -070053import com.android.services.telephony.rcs.SipTransportController;
James.cf Linc9f35a42020-01-15 02:35:22 +080054import com.android.services.telephony.rcs.TelephonyRcsService;
James.cf Lin99a360d2020-11-04 10:48:37 +080055import com.android.services.telephony.rcs.UceControllerManager;
James.cf Lincad981c2019-12-10 20:37:56 +080056
James.cf Linaf3183c2019-10-24 00:59:00 +080057import java.util.List;
Brad Ebingerd4c5bde2021-02-12 06:18:28 +000058import java.util.Set;
James.cf Linaf3183c2019-10-24 00:59:00 +080059
60/**
61 * Implementation of the IImsRcsController interface.
62 */
63public class ImsRcsController extends IImsRcsController.Stub {
64 private static final String TAG = "ImsRcsController";
65
66 /** The singleton instance. */
67 private static ImsRcsController sInstance;
68
69 private PhoneGlobals mApp;
James.cf Linc9f35a42020-01-15 02:35:22 +080070 private TelephonyRcsService mRcsService;
Brad Ebingere3ae65a2020-09-11 12:45:11 -070071 private ImsResolver mImsResolver;
Brad Ebinger49a72b42021-01-29 00:55:24 +000072 // set by shell cmd phone src set-device-enabled true/false
73 private Boolean mSingleRegistrationOverride;
James.cf Linaf3183c2019-10-24 00:59:00 +080074
75 /**
76 * Initialize the singleton ImsRcsController instance.
77 * This is only done once, at startup, from PhoneApp.onCreate().
78 */
79 static ImsRcsController init(PhoneGlobals app) {
80 synchronized (ImsRcsController.class) {
81 if (sInstance == null) {
82 sInstance = new ImsRcsController(app);
83 } else {
84 Log.wtf(TAG, "init() called multiple times! sInstance = " + sInstance);
85 }
86 return sInstance;
87 }
88 }
89
90 /** Private constructor; @see init() */
91 private ImsRcsController(PhoneGlobals app) {
92 Log.i(TAG, "ImsRcsController");
93 mApp = app;
Peter Wangc035ce42020-01-08 21:00:22 -080094 TelephonyFrameworkInitializer
95 .getTelephonyServiceManager().getTelephonyImsServiceRegisterer().register(this);
Brad Ebingerd1947d82021-05-17 20:54:49 +000096 mImsResolver = ImsResolver.getInstance();
James.cf Linaf3183c2019-10-24 00:59:00 +080097 }
98
James.cf Lincad981c2019-12-10 20:37:56 +080099 /**
Brad Ebingera68a4972020-01-30 17:31:23 -0800100 * Register a {@link RegistrationManager.RegistrationCallback} to receive IMS network
101 * registration state.
James.cf Lindc2d5422019-12-31 14:40:25 +0800102 */
103 @Override
Brad Ebingera68a4972020-01-30 17:31:23 -0800104 public void registerImsRegistrationCallback(int subId, IImsRegistrationCallback callback) {
Nathan Harold75a9ff12021-04-06 11:26:02 -0700105 TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
James.cf Linf020d162021-01-31 22:15:52 +0800106 mApp, subId, "registerImsRegistrationCallback");
James.cf Lindc2d5422019-12-31 14:40:25 +0800107 final long token = Binder.clearCallingIdentity();
108 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800109 getRcsFeatureController(subId).registerImsRegistrationCallback(subId, callback);
110 } catch (ImsException e) {
James.cf Lindc2d5422019-12-31 14:40:25 +0800111 Log.e(TAG, "registerImsRegistrationCallback: sudId=" + subId + ", " + e.getMessage());
112 throw new ServiceSpecificException(e.getCode());
113 } finally {
114 Binder.restoreCallingIdentity(token);
115 }
116 }
117
118 /**
Brad Ebingera68a4972020-01-30 17:31:23 -0800119 * Removes an existing {@link RegistrationManager.RegistrationCallback}.
James.cf Lindc2d5422019-12-31 14:40:25 +0800120 */
121 @Override
122 public void unregisterImsRegistrationCallback(int subId, IImsRegistrationCallback callback) {
Nathan Harold75a9ff12021-04-06 11:26:02 -0700123 TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
James.cf Linf020d162021-01-31 22:15:52 +0800124 mApp, subId, "unregisterImsRegistrationCallback");
James.cf Lindc2d5422019-12-31 14:40:25 +0800125 final long token = Binder.clearCallingIdentity();
126 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800127 getRcsFeatureController(subId).unregisterImsRegistrationCallback(subId, callback);
James.cf Lindc2d5422019-12-31 14:40:25 +0800128 } catch (ServiceSpecificException e) {
129 Log.e(TAG, "unregisterImsRegistrationCallback: error=" + e.errorCode);
130 } finally {
131 Binder.restoreCallingIdentity(token);
132 }
133 }
134
135 /**
136 * Get the IMS service registration state for the RcsFeature associated with this sub id.
137 */
138 @Override
139 public void getImsRcsRegistrationState(int subId, IIntegerConsumer consumer) {
Nathan Harold75a9ff12021-04-06 11:26:02 -0700140 TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
James.cf Linf020d162021-01-31 22:15:52 +0800141 mApp, subId, "getImsRcsRegistrationState");
James.cf Lindc2d5422019-12-31 14:40:25 +0800142 final long token = Binder.clearCallingIdentity();
143 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800144 getRcsFeatureController(subId).getRegistrationState(regState -> {
James.cf Lindc2d5422019-12-31 14:40:25 +0800145 try {
146 consumer.accept((regState == null)
147 ? RegistrationManager.REGISTRATION_STATE_NOT_REGISTERED : regState);
148 } catch (RemoteException e) {
149 Log.w(TAG, "getImsRcsRegistrationState: callback is not available.");
150 }
151 });
152 } finally {
153 Binder.restoreCallingIdentity(token);
154 }
155 }
156
157 /**
158 * Gets the Transport Type associated with the current IMS RCS registration.
159 */
160 @Override
161 public void getImsRcsRegistrationTransportType(int subId, IIntegerConsumer consumer) {
Nathan Harold75a9ff12021-04-06 11:26:02 -0700162 TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
James.cf Linf020d162021-01-31 22:15:52 +0800163 mApp, subId, "getImsRcsRegistrationTransportType");
James.cf Lindc2d5422019-12-31 14:40:25 +0800164 final long token = Binder.clearCallingIdentity();
165 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800166 getRcsFeatureController(subId).getRegistrationTech(regTech -> {
James.cf Lindc2d5422019-12-31 14:40:25 +0800167 // Convert registration tech from ImsRegistrationImplBase -> RegistrationManager
168 int regTechConverted = (regTech == null)
169 ? ImsRegistrationImplBase.REGISTRATION_TECH_NONE : regTech;
170 regTechConverted = RegistrationManager.IMS_REG_TO_ACCESS_TYPE_MAP.get(
171 regTechConverted);
172 try {
173 consumer.accept(regTechConverted);
174 } catch (RemoteException e) {
175 Log.w(TAG, "getImsRcsRegistrationTransportType: callback is not available.");
176 }
177 });
178 } finally {
179 Binder.restoreCallingIdentity(token);
180 }
181 }
182
183 /**
James.cf Lincad981c2019-12-10 20:37:56 +0800184 * Register a capability callback which will provide RCS availability updates for the
185 * subscription specified.
186 *
187 * @param subId the subscription ID
188 * @param callback The ImsCapabilityCallback to be registered.
189 */
James.cf Linaf3183c2019-10-24 00:59:00 +0800190 @Override
Brad Ebingera68a4972020-01-30 17:31:23 -0800191 public void registerRcsAvailabilityCallback(int subId, IImsCapabilityCallback callback) {
James.cf Linaf3183c2019-10-24 00:59:00 +0800192 enforceReadPrivilegedPermission("registerRcsAvailabilityCallback");
James.cf Lincad981c2019-12-10 20:37:56 +0800193 final long token = Binder.clearCallingIdentity();
194 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800195 getRcsFeatureController(subId).registerRcsAvailabilityCallback(subId, callback);
196 } catch (ImsException e) {
James.cf Lincad981c2019-12-10 20:37:56 +0800197 Log.e(TAG, "registerRcsAvailabilityCallback: sudId=" + subId + ", " + e.getMessage());
198 throw new ServiceSpecificException(e.getCode());
199 } finally {
200 Binder.restoreCallingIdentity(token);
201 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800202 }
203
James.cf Lincad981c2019-12-10 20:37:56 +0800204 /**
205 * Remove the registered capability callback.
206 *
207 * @param subId the subscription ID
208 * @param callback The ImsCapabilityCallback to be removed.
209 */
James.cf Linaf3183c2019-10-24 00:59:00 +0800210 @Override
James.cf Lincad981c2019-12-10 20:37:56 +0800211 public void unregisterRcsAvailabilityCallback(int subId, IImsCapabilityCallback callback) {
James.cf Linaf3183c2019-10-24 00:59:00 +0800212 enforceReadPrivilegedPermission("unregisterRcsAvailabilityCallback");
James.cf Lincad981c2019-12-10 20:37:56 +0800213 final long token = Binder.clearCallingIdentity();
214 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800215 getRcsFeatureController(subId).unregisterRcsAvailabilityCallback(subId, callback);
Brad Ebinger919631e2021-06-02 17:46:35 -0700216 } catch (ServiceSpecificException e) {
217 Log.e(TAG, "unregisterRcsAvailabilityCallback: error=" + e.errorCode);
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");
Brad Ebingera68a4972020-01-30 17:31:23 -0800279 final long token = Binder.clearCallingIdentity();
280 try {
James.cf Lin99a360d2020-11-04 10:48:37 +0800281 UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
282 UceControllerManager.class);
283 if (uceCtrlManager == null) {
Brad Ebingera68a4972020-01-30 17:31:23 -0800284 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
285 "This subscription does not support UCE.");
286 }
James.cf Lin99a360d2020-11-04 10:48:37 +0800287 uceCtrlManager.requestCapabilities(contactNumbers, c);
288 } catch (ImsException e) {
289 throw new ServiceSpecificException(e.getCode(), e.getMessage());
Brad Ebingera68a4972020-01-30 17:31:23 -0800290 } finally {
291 Binder.restoreCallingIdentity(token);
Brad Ebinger1aa94992020-01-22 14:17:23 -0800292 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800293 }
294
295 @Override
James.cf Linbcdf8b32021-01-14 16:44:13 +0800296 public void requestAvailability(int subId, String callingPackage,
James.cf Lin64e91212020-10-30 01:09:52 +0800297 String callingFeatureId, Uri contactNumber, IRcsUceControllerCallback c) {
James.cf Lin051dd252021-01-21 03:30:54 +0800298 enforceAccessUserCapabilityExchangePermission("requestAvailability");
299 enforceReadContactsPermission("requestAvailability");
Brad Ebingera68a4972020-01-30 17:31:23 -0800300 final long token = Binder.clearCallingIdentity();
301 try {
James.cf Lin99a360d2020-11-04 10:48:37 +0800302 UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
303 UceControllerManager.class);
304 if (uceCtrlManager == null) {
Brad Ebingera68a4972020-01-30 17:31:23 -0800305 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
306 "This subscription does not support UCE.");
307 }
James.cf Lin99a360d2020-11-04 10:48:37 +0800308 uceCtrlManager.requestNetworkAvailability(contactNumber, c);
309 } catch (ImsException e) {
310 throw new ServiceSpecificException(e.getCode(), e.getMessage());
311 } finally {
312 Binder.restoreCallingIdentity(token);
313 }
314 }
315
316 @Override
317 public @PublishState int getUcePublishState(int subId) {
318 enforceReadPrivilegedPermission("getUcePublishState");
319 final long token = Binder.clearCallingIdentity();
320 try {
321 UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
322 UceControllerManager.class);
323 if (uceCtrlManager == null) {
324 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
325 "This subscription does not support UCE.");
326 }
327 return uceCtrlManager.getUcePublishState();
328 } catch (ImsException e) {
329 throw new ServiceSpecificException(e.getCode(), e.getMessage());
330 } finally {
331 Binder.restoreCallingIdentity(token);
332 }
333 }
334
Brad Ebingerd4c5bde2021-02-12 06:18:28 +0000335 /**
336 * Add new feature tags to the Set used to calculate the capabilities in PUBLISH.
337 */
338 // Used for SHELL command only right now.
339 public RcsContactUceCapability addUceRegistrationOverrideShell(int subId,
340 Set<String> featureTags) throws ImsException {
341 // Permission check happening in PhoneInterfaceManager.
Brad Ebinger919631e2021-06-02 17:46:35 -0700342 try {
343 UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
344 UceControllerManager.class);
345 if (uceCtrlManager == null) {
346 return null;
347 }
348 return uceCtrlManager.addUceRegistrationOverride(featureTags);
349 } catch (ServiceSpecificException e) {
350 throw new ImsException(e.getMessage(), e.errorCode);
Brad Ebingerd4c5bde2021-02-12 06:18:28 +0000351 }
Brad Ebingerd4c5bde2021-02-12 06:18:28 +0000352 }
353
354 /**
355 * Remove existing feature tags to the Set used to calculate the capabilities in PUBLISH.
356 */
357 // Used for SHELL command only right now.
358 public RcsContactUceCapability removeUceRegistrationOverrideShell(int subId,
359 Set<String> featureTags) throws ImsException {
360 // Permission check happening in PhoneInterfaceManager.
Brad Ebinger919631e2021-06-02 17:46:35 -0700361 try {
362 UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
363 UceControllerManager.class);
364 if (uceCtrlManager == null) {
365 return null;
366 }
367 return uceCtrlManager.removeUceRegistrationOverride(featureTags);
368 } catch (ServiceSpecificException e) {
369 throw new ImsException(e.getMessage(), e.errorCode);
Brad Ebingerd4c5bde2021-02-12 06:18:28 +0000370 }
Brad Ebingerd4c5bde2021-02-12 06:18:28 +0000371 }
372
373 /**
374 * Clear all overrides in the Set used to calculate the capabilities in PUBLISH.
375 */
376 // Used for SHELL command only right now.
377 public RcsContactUceCapability clearUceRegistrationOverrideShell(int subId)
378 throws ImsException {
Brad Ebinger919631e2021-06-02 17:46:35 -0700379 try {
380 // Permission check happening in PhoneInterfaceManager.
381 UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
382 UceControllerManager.class);
383 if (uceCtrlManager == null) {
384 return null;
385 }
386 return uceCtrlManager.clearUceRegistrationOverride();
387 } catch (ServiceSpecificException e) {
388 throw new ImsException(e.getMessage(), e.errorCode);
Brad Ebingerd4c5bde2021-02-12 06:18:28 +0000389 }
Brad Ebingerd4c5bde2021-02-12 06:18:28 +0000390 }
391
392 /**
393 * @return current RcsContactUceCapability instance that will be used for PUBLISH.
394 */
395 // Used for SHELL command only right now.
396 public RcsContactUceCapability getLatestRcsContactUceCapabilityShell(int subId)
397 throws ImsException {
Brad Ebinger919631e2021-06-02 17:46:35 -0700398 try {
399 // Permission check happening in PhoneInterfaceManager.
400 UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
401 UceControllerManager.class);
402 if (uceCtrlManager == null) {
403 return null;
404 }
405 return uceCtrlManager.getLatestRcsContactUceCapability();
406 } catch (ServiceSpecificException e) {
407 throw new ImsException(e.getMessage(), e.errorCode);
Brad Ebingerd4c5bde2021-02-12 06:18:28 +0000408 }
Brad Ebingerd4c5bde2021-02-12 06:18:28 +0000409 }
410
411 /**
412 * @return the PIDf XML used in the last PUBLISH procedure or "none" if the device is not
413 * published. Returns {@code null} if the operation failed due to an error.
414 */
415 // Used for SHELL command only right now.
416 public String getLastUcePidfXmlShell(int subId) throws ImsException {
Brad Ebinger919631e2021-06-02 17:46:35 -0700417 try {
418 // Permission check happening in PhoneInterfaceManager.
419 UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
420 UceControllerManager.class);
421 if (uceCtrlManager == null) {
422 return null;
423 }
424 String pidfXml = uceCtrlManager.getLastPidfXml();
425 return pidfXml == null ? "none" : pidfXml;
426 } catch (ServiceSpecificException e) {
427 throw new ImsException(e.getMessage(), e.errorCode);
Brad Ebingerd4c5bde2021-02-12 06:18:28 +0000428 }
Brad Ebingerd4c5bde2021-02-12 06:18:28 +0000429 }
430
James.cf Line8713a42021-04-29 16:04:26 +0800431 /**
432 * Remove UCE requests cannot be sent to the network status.
433 * @return true if this command is successful.
434 */
435 // Used for SHELL command only right now.
436 public boolean removeUceRequestDisallowedStatus(int subId) throws ImsException {
Brad Ebinger919631e2021-06-02 17:46:35 -0700437 try {
James.cf Linc6b449f2021-06-05 01:11:15 +0800438 UceControllerManager uceCtrlManager = getRcsFeatureController(subId, true).getFeature(
Brad Ebinger919631e2021-06-02 17:46:35 -0700439 UceControllerManager.class);
440 if (uceCtrlManager == null) {
441 return false;
442 }
443 return uceCtrlManager.removeUceRequestDisallowedStatus();
444 } catch (ServiceSpecificException e) {
445 throw new ImsException(e.getMessage(), e.errorCode);
James.cf Line8713a42021-04-29 16:04:26 +0800446 }
James.cf Line8713a42021-04-29 16:04:26 +0800447 }
448
James.cf Lin0fc71b02021-05-25 01:37:38 +0800449 /**
450 * Set the timeout for contact capabilities request.
451 */
452 // Used for SHELL command only right now.
453 public boolean setCapabilitiesRequestTimeout(int subId, long timeoutAfter) throws ImsException {
Brad Ebinger919631e2021-06-02 17:46:35 -0700454 try {
James.cf Linc6b449f2021-06-05 01:11:15 +0800455 UceControllerManager uceCtrlManager = getRcsFeatureController(subId, true).getFeature(
Brad Ebinger919631e2021-06-02 17:46:35 -0700456 UceControllerManager.class);
457 if (uceCtrlManager == null) {
458 return false;
459 }
460 return uceCtrlManager.setCapabilitiesRequestTimeout(timeoutAfter);
461 } catch (ServiceSpecificException e) {
462 throw new ImsException(e.getMessage(), e.errorCode);
James.cf Lin0fc71b02021-05-25 01:37:38 +0800463 }
James.cf Lin0fc71b02021-05-25 01:37:38 +0800464 }
465
James.cf Lin99a360d2020-11-04 10:48:37 +0800466 @Override
467 public void registerUcePublishStateCallback(int subId, IRcsUcePublishStateCallback c) {
468 enforceReadPrivilegedPermission("registerUcePublishStateCallback");
469 final long token = Binder.clearCallingIdentity();
470 try {
471 UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
472 UceControllerManager.class);
473 if (uceCtrlManager == null) {
474 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
475 "This subscription does not support UCE.");
476 }
477 uceCtrlManager.registerPublishStateCallback(c);
478 } catch (ImsException e) {
479 throw new ServiceSpecificException(e.getCode(), e.getMessage());
480 } finally {
481 Binder.restoreCallingIdentity(token);
482 }
483 }
484
485 @Override
486 public void unregisterUcePublishStateCallback(int subId, IRcsUcePublishStateCallback c) {
487 enforceReadPrivilegedPermission("unregisterUcePublishStateCallback");
488 final long token = Binder.clearCallingIdentity();
489 try {
490 UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
491 UceControllerManager.class);
492 if (uceCtrlManager == null) {
493 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
494 "This subscription does not support UCE.");
495 }
496 uceCtrlManager.unregisterPublishStateCallback(c);
Brad Ebinger919631e2021-06-02 17:46:35 -0700497 } catch (ServiceSpecificException e) {
498 Log.e(TAG, "unregisterUcePublishStateCallback: error=" + e.errorCode);
Brad Ebingera68a4972020-01-30 17:31:23 -0800499 } finally {
500 Binder.restoreCallingIdentity(token);
Brad Ebinger1aa94992020-01-22 14:17:23 -0800501 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800502 }
503
504 @Override
Brad Ebinger8b79edc2020-02-27 19:13:24 -0800505 public boolean isUceSettingEnabled(int subId, String callingPackage, String callingFeatureId) {
506 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
507 mApp, subId, callingPackage, callingFeatureId, "isUceSettingEnabled")) {
508 Log.w(TAG, "isUceSettingEnabled: READ_PHONE_STATE app op disabled when accessing "
509 + "isUceSettingEnabled");
510 return false;
511 }
512 final long token = Binder.clearCallingIdentity();
513 try {
514 return SubscriptionManager.getBooleanSubscriptionProperty(subId,
515 SubscriptionManager.IMS_RCS_UCE_ENABLED, false /*defaultValue*/, mApp);
516 } finally {
517 Binder.restoreCallingIdentity(token);
518 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800519 }
520
521 @Override
522 public void setUceSettingEnabled(int subId, boolean isEnabled) {
523 enforceModifyPermission();
Brad Ebinger8b79edc2020-02-27 19:13:24 -0800524 final long token = Binder.clearCallingIdentity();
525 try {
526 SubscriptionManager.setSubscriptionProperty(subId,
527 SubscriptionManager.IMS_RCS_UCE_ENABLED, (isEnabled ? "1" : "0"));
528 } finally {
529 Binder.restoreCallingIdentity(token);
530 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800531 }
532
Brad Ebingerb989c7c2020-09-23 17:03:48 -0700533 @Override
534 public boolean isSipDelegateSupported(int subId) {
Brad Ebinger4df7e242021-02-17 23:23:21 +0000535 TelephonyPermissions.enforceAnyPermissionGranted(mApp, Binder.getCallingUid(),
536 "isSipDelegateSupported",
537 Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION,
538 Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
Brad Ebinger49a72b42021-01-29 00:55:24 +0000539 if (!isImsSingleRegistrationSupportedOnDevice()) {
540 return false;
541 }
Brad Ebingerb989c7c2020-09-23 17:03:48 -0700542 final long token = Binder.clearCallingIdentity();
543 try {
544 SipTransportController transport = getRcsFeatureController(subId).getFeature(
545 SipTransportController.class);
546 if (transport == null) {
547 return false;
548 }
549 return transport.isSupported(subId);
550 } catch (ImsException e) {
551 throw new ServiceSpecificException(e.getCode(), e.getMessage());
552 } catch (ServiceSpecificException e) {
553 if (e.errorCode == ImsException.CODE_ERROR_UNSUPPORTED_OPERATION) {
554 return false;
555 }
556 throw e;
557 } finally {
558 Binder.restoreCallingIdentity(token);
559 }
560 }
561
Brad Ebingeraf1e9832020-10-14 10:49:28 -0700562 @Override
Brad Ebinger63b6f5a2020-10-27 11:43:35 -0700563 public void createSipDelegate(int subId, DelegateRequest request, String packageName,
Brad Ebingeraf1e9832020-10-14 10:49:28 -0700564 ISipDelegateConnectionStateCallback delegateState,
565 ISipDelegateMessageCallback delegateMessage) {
Brad Ebinger4df7e242021-02-17 23:23:21 +0000566 enforceImsSingleRegistrationPermission("createSipDelegate");
Brad Ebinger49a72b42021-01-29 00:55:24 +0000567 if (!isImsSingleRegistrationSupportedOnDevice()) {
568 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
569 "SipDelegate creation is only supported for devices supporting IMS single "
570 + "registration");
571 }
Brad Ebinger63b6f5a2020-10-27 11:43:35 -0700572 if (!UserHandle.getUserHandleForUid(Binder.getCallingUid()).isSystem()) {
573 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
574 "SipDelegate creation is only available to primary user.");
575 }
576 try {
577 int remoteUid = mApp.getPackageManager().getPackageUid(packageName, 0 /*flags*/);
578 if (Binder.getCallingUid() != remoteUid) {
579 throw new SecurityException("passed in packageName does not match the caller");
580 }
581 } catch (PackageManager.NameNotFoundException e) {
582 throw new SecurityException("Passed in PackageName can not be found on device");
583 }
Brad Ebingeraf1e9832020-10-14 10:49:28 -0700584
Jinyoung Jeongca77e1c2021-10-21 04:34:46 +0000585 final int uid = Binder.getCallingUid();
Brad Ebingeraf1e9832020-10-14 10:49:28 -0700586 final long identity = Binder.clearCallingIdentity();
587 SipTransportController transport = getRcsFeatureController(subId).getFeature(
588 SipTransportController.class);
589 if (transport == null) {
590 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
591 "This subscription does not support the creation of SIP delegates");
592 }
593 try {
Jinyoung Jeongca77e1c2021-10-21 04:34:46 +0000594 transport.createSipDelegate(subId, uid, request, packageName, delegateState,
Brad Ebinger63b6f5a2020-10-27 11:43:35 -0700595 delegateMessage);
Brad Ebingeraf1e9832020-10-14 10:49:28 -0700596 } catch (ImsException e) {
597 throw new ServiceSpecificException(e.getCode(), e.getMessage());
598 } finally {
599 Binder.restoreCallingIdentity(identity);
600 }
601 }
602
603 @Override
604 public void destroySipDelegate(int subId, ISipDelegate connection, int reason) {
Brad Ebinger652411e2021-06-30 09:30:35 -0700605 // Do not check permissions here - the caller needs to have a connection already from the
606 // create method to call this method.
607 if (connection == null) {
608 return;
609 }
Brad Ebingeraf1e9832020-10-14 10:49:28 -0700610 final long identity = Binder.clearCallingIdentity();
611 try {
Brad Ebinger63b6f5a2020-10-27 11:43:35 -0700612 SipTransportController transport = getRcsFeatureController(subId).getFeature(
613 SipTransportController.class);
614 if (transport == null) {
615 return;
616 }
617 transport.destroySipDelegate(subId, connection, reason);
Brad Ebinger919631e2021-06-02 17:46:35 -0700618 } catch (ServiceSpecificException e) {
619 Log.e(TAG, "destroySipDelegate: error=" + e.errorCode);
Brad Ebingeraf1e9832020-10-14 10:49:28 -0700620 } finally {
621 Binder.restoreCallingIdentity(identity);
622 }
623 }
624
Brad Ebinger36221382020-12-09 00:33:39 +0000625 @Override
626 public void triggerNetworkRegistration(int subId, ISipDelegate connection, int sipCode,
627 String sipReason) {
Brad Ebinger4df7e242021-02-17 23:23:21 +0000628 enforceImsSingleRegistrationPermission("triggerNetworkRegistration");
Brad Ebinger36221382020-12-09 00:33:39 +0000629
630 final long identity = Binder.clearCallingIdentity();
631 try {
632 SipTransportController transport = getRcsFeatureController(subId).getFeature(
633 SipTransportController.class);
634 if (transport == null) {
635 return;
636 }
637 transport.triggerFullNetworkRegistration(subId, connection, sipCode, sipReason);
Brad Ebinger919631e2021-06-02 17:46:35 -0700638 } catch (ServiceSpecificException e) {
639 Log.e(TAG, "triggerNetworkRegistration: error=" + e.errorCode);
Brad Ebinger36221382020-12-09 00:33:39 +0000640 } finally {
641 Binder.restoreCallingIdentity(identity);
642 }
643 }
644
James.cf Linaf3183c2019-10-24 00:59:00 +0800645 /**
Brad Ebingere3ae65a2020-09-11 12:45:11 -0700646 * Registers for updates to the RcsFeature connection through the IImsServiceFeatureCallback
647 * callback.
648 */
649 @Override
Brad Ebinger6366ce92020-10-01 13:51:05 -0700650 public void registerRcsFeatureCallback(int slotId, IImsServiceFeatureCallback callback) {
Brad Ebingere3ae65a2020-09-11 12:45:11 -0700651 enforceModifyPermission();
652
653 final long identity = Binder.clearCallingIdentity();
654 try {
655 if (mImsResolver == null) {
656 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
657 "Device does not support IMS");
658 }
Brad Ebinger6366ce92020-10-01 13:51:05 -0700659 mImsResolver.listenForFeature(slotId, ImsFeature.FEATURE_RCS, callback);
Brad Ebingere3ae65a2020-09-11 12:45:11 -0700660 } finally {
661 Binder.restoreCallingIdentity(identity);
662 }
663 }
Brad Ebinger6366ce92020-10-01 13:51:05 -0700664
Brad Ebingere3ae65a2020-09-11 12:45:11 -0700665 /**
666 * Unregister a previously registered IImsServiceFeatureCallback associated with an ImsFeature.
667 */
668 @Override
669 public void unregisterImsFeatureCallback(IImsServiceFeatureCallback callback) {
670 enforceModifyPermission();
671
672 final long identity = Binder.clearCallingIdentity();
673 try {
674 if (mImsResolver == null) return;
675 mImsResolver.unregisterImsFeatureCallback(callback);
676 } finally {
677 Binder.restoreCallingIdentity(identity);
678 }
679 }
680
681 /**
James.cf Linaf3183c2019-10-24 00:59:00 +0800682 * Make sure either called from same process as self (phone) or IPC caller has read privilege.
683 *
684 * @throws SecurityException if the caller does not have the required permission
685 */
686 private void enforceReadPrivilegedPermission(String message) {
687 mApp.enforceCallingOrSelfPermission(
688 android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, message);
689 }
690
691 /**
Brad Ebinger4df7e242021-02-17 23:23:21 +0000692 * @throws SecurityException if the caller does not have the required
693 * PERFORM_IMS_SINGLE_REGISTRATION permission.
694 */
695 private void enforceImsSingleRegistrationPermission(String message) {
696 mApp.enforceCallingOrSelfPermission(
697 Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION, message);
698 }
699
700 /**
James.cf Linaf3183c2019-10-24 00:59:00 +0800701 * Make sure the caller has the MODIFY_PHONE_STATE permission.
702 *
703 * @throws SecurityException if the caller does not have the required permission
704 */
705 private void enforceModifyPermission() {
706 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE, null);
707 }
James.cf Lincad981c2019-12-10 20:37:56 +0800708
709 /**
James.cf Lin051dd252021-01-21 03:30:54 +0800710 * Make sure the caller has the ACCESS_RCS_USER_CAPABILITY_EXCHANGE permission.
711 *
712 * @throws SecurityException if the caller does not have the required permission.
713 */
714 private void enforceAccessUserCapabilityExchangePermission(String message) {
715 mApp.enforceCallingOrSelfPermission(
716 android.Manifest.permission.ACCESS_RCS_USER_CAPABILITY_EXCHANGE, message);
717 }
718
719 /**
720 * Make sure the caller has the READ_CONTACTS permission.
721 *
722 * @throws SecurityException if the caller does not have the required permission.
723 */
724 private void enforceReadContactsPermission(String message) {
725 mApp.enforceCallingOrSelfPermission(
726 android.Manifest.permission.READ_CONTACTS, message);
727 }
728
729 /**
James.cf Lindc2d5422019-12-31 14:40:25 +0800730 * Retrieve RcsFeatureManager instance.
731 *
732 * @param subId the subscription ID
733 * @return The RcsFeatureManager instance
734 * @throws ServiceSpecificException if getting RcsFeatureManager instance failed.
735 */
Brad Ebingera68a4972020-01-30 17:31:23 -0800736 private RcsFeatureController getRcsFeatureController(int subId) {
James.cf Linc6b449f2021-06-05 01:11:15 +0800737 return getRcsFeatureController(subId, false /* skipVerifyingConfig */);
738 }
739
740 /**
741 * Retrieve RcsFeatureManager instance.
742 *
743 * @param subId the subscription ID
744 * @param skipVerifyingConfig If the RCS configuration can be skip.
745 * @return The RcsFeatureManager instance
746 * @throws ServiceSpecificException if getting RcsFeatureManager instance failed.
747 */
748 private RcsFeatureController getRcsFeatureController(int subId, boolean skipVerifyingConfig) {
James.cf Lindc2d5422019-12-31 14:40:25 +0800749 if (!ImsManager.isImsSupportedOnDevice(mApp)) {
James.cf Lincad981c2019-12-10 20:37:56 +0800750 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
James.cf Lindc2d5422019-12-31 14:40:25 +0800751 "IMS is not available on device.");
752 }
Brad Ebingera68a4972020-01-30 17:31:23 -0800753 if (mRcsService == null) {
754 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
755 "IMS is not available on device.");
756 }
James.cf Lindc2d5422019-12-31 14:40:25 +0800757 Phone phone = PhoneGlobals.getPhone(subId);
758 if (phone == null) {
759 throw new ServiceSpecificException(ImsException.CODE_ERROR_INVALID_SUBSCRIPTION,
760 "Invalid subscription Id: " + subId);
761 }
Brad Ebingera68a4972020-01-30 17:31:23 -0800762 int slotId = phone.getPhoneId();
James.cf Linc6b449f2021-06-05 01:11:15 +0800763 if (!skipVerifyingConfig) {
764 verifyImsRcsConfiguredOrThrow(slotId);
765 }
Brad Ebingera68a4972020-01-30 17:31:23 -0800766 RcsFeatureController c = mRcsService.getFeatureController(slotId);
767 if (c == null) {
Brad Ebinger036dc9e2020-02-06 15:49:06 -0800768 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
769 "The requested operation is not supported for subId " + subId);
James.cf Lincad981c2019-12-10 20:37:56 +0800770 }
Brad Ebingera68a4972020-01-30 17:31:23 -0800771 return c;
James.cf Lincad981c2019-12-10 20:37:56 +0800772 }
James.cf Linc9f35a42020-01-15 02:35:22 +0800773
Brad Ebinger919631e2021-06-02 17:46:35 -0700774 /**
775 * Throw an ImsException if the IMS resolver does not have an ImsService configured for RCS
776 * for the given slot ID or no ImsResolver instance has been created.
777 * @param slotId The slot ID that the IMS service is created for.
778 * @throws ServiceSpecificException If there is no ImsService configured for this slot.
779 */
780 private void verifyImsRcsConfiguredOrThrow(int slotId) {
781 if (mImsResolver == null
782 || !mImsResolver.isImsServiceConfiguredForFeature(slotId, ImsFeature.FEATURE_RCS)) {
783 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
784 "This subscription does not support RCS");
785 }
786 }
787
Brad Ebinger49a72b42021-01-29 00:55:24 +0000788 private boolean isImsSingleRegistrationSupportedOnDevice() {
789 return mSingleRegistrationOverride != null ? mSingleRegistrationOverride
790 : mApp.getPackageManager().hasSystemFeature(
791 PackageManager.FEATURE_TELEPHONY_IMS_SINGLE_REGISTRATION);
792 }
793
James.cf Linc9f35a42020-01-15 02:35:22 +0800794 void setRcsService(TelephonyRcsService rcsService) {
795 mRcsService = rcsService;
796 }
Brad Ebinger49a72b42021-01-29 00:55:24 +0000797
798 /**
799 * Override device RCS single registration support check for CTS testing or remove override
800 * if the Boolean is set to null.
801 */
802 void setDeviceSingleRegistrationSupportOverride(Boolean deviceOverrideValue) {
803 mSingleRegistrationOverride = deviceOverrideValue;
804 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800805}