blob: 5e616b71f4cad4830642146e5a8cc52c709aab52 [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;
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;
59
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 Ebingere3ae65a2020-09-11 12:45:11 -070096 mImsResolver = mApp.getImsResolver();
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) {
James.cf Linf020d162021-01-31 22:15:52 +0800105 TelephonyPermissions.enforeceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
106 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) {
James.cf Linf020d162021-01-31 22:15:52 +0800123 TelephonyPermissions.enforeceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
124 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) {
James.cf Linf020d162021-01-31 22:15:52 +0800140 TelephonyPermissions.enforeceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
141 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) {
James.cf Linf020d162021-01-31 22:15:52 +0800162 TelephonyPermissions.enforeceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
163 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);
James.cf Lincad981c2019-12-10 20:37:56 +0800216 } finally {
217 Binder.restoreCallingIdentity(token);
218 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800219 }
220
James.cf Lincad981c2019-12-10 20:37:56 +0800221 /**
222 * Query for the capability of an IMS RCS service
223 *
224 * @param subId the subscription ID
225 * @param capability the RCS capability to query.
James.cf Linf020d162021-01-31 22:15:52 +0800226 * @param radioTech the radio technology type that we are querying.
James.cf Lincad981c2019-12-10 20:37:56 +0800227 * @return true if the RCS capability is capable for this subscription, false otherwise.
228 */
James.cf Linaf3183c2019-10-24 00:59:00 +0800229 @Override
230 public boolean isCapable(int subId,
James.cf Lincad981c2019-12-10 20:37:56 +0800231 @RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability,
232 @ImsRegistrationImplBase.ImsRegistrationTech int radioTech) {
James.cf Linaf3183c2019-10-24 00:59:00 +0800233 enforceReadPrivilegedPermission("isCapable");
James.cf Lincad981c2019-12-10 20:37:56 +0800234 final long token = Binder.clearCallingIdentity();
235 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800236 return getRcsFeatureController(subId).isCapable(capability, radioTech);
237 } catch (ImsException e) {
James.cf Lincad981c2019-12-10 20:37:56 +0800238 Log.e(TAG, "isCapable: sudId=" + subId
239 + ", capability=" + capability + ", " + e.getMessage());
240 return false;
241 } finally {
242 Binder.restoreCallingIdentity(token);
243 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800244 }
245
James.cf Lincad981c2019-12-10 20:37:56 +0800246 /**
247 * Query the availability of an IMS RCS capability.
248 *
249 * @param subId the subscription ID
250 * @param capability the RCS capability to query.
251 * @return true if the RCS capability is currently available for the associated subscription,
James.cf Linf020d162021-01-31 22:15:52 +0800252 * @param radioTech the radio technology type that we are querying.
James.cf Lincad981c2019-12-10 20:37:56 +0800253 * false otherwise.
254 */
James.cf Linaf3183c2019-10-24 00:59:00 +0800255 @Override
256 public boolean isAvailable(int subId,
James.cf Linf020d162021-01-31 22:15:52 +0800257 @RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability,
258 @ImsRegistrationImplBase.ImsRegistrationTech int radioTech) {
James.cf Linaf3183c2019-10-24 00:59:00 +0800259 enforceReadPrivilegedPermission("isAvailable");
James.cf Lincad981c2019-12-10 20:37:56 +0800260 final long token = Binder.clearCallingIdentity();
261 try {
James.cf Linf020d162021-01-31 22:15:52 +0800262 return getRcsFeatureController(subId).isAvailable(capability, radioTech);
Brad Ebingera68a4972020-01-30 17:31:23 -0800263 } catch (ImsException e) {
James.cf Lincad981c2019-12-10 20:37:56 +0800264 Log.e(TAG, "isAvailable: sudId=" + subId
265 + ", capability=" + capability + ", " + e.getMessage());
266 return false;
267 } finally {
268 Binder.restoreCallingIdentity(token);
269 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800270 }
271
272 @Override
Brad Ebinger8b79edc2020-02-27 19:13:24 -0800273 public void requestCapabilities(int subId, String callingPackage, String callingFeatureId,
274 List<Uri> contactNumbers, IRcsUceControllerCallback c) {
James.cf Lin051dd252021-01-21 03:30:54 +0800275 enforceAccessUserCapabilityExchangePermission("requestCapabilities");
276 enforceReadContactsPermission("requestCapabilities");
277 if (!isCallingProcessInForeground(Binder.getCallingUid())) {
278 throw new SecurityException("The caller is not in the foreground.");
279 }
Brad Ebingera68a4972020-01-30 17:31:23 -0800280 final long token = Binder.clearCallingIdentity();
281 try {
James.cf Lin99a360d2020-11-04 10:48:37 +0800282 UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
283 UceControllerManager.class);
284 if (uceCtrlManager == null) {
Brad Ebingera68a4972020-01-30 17:31:23 -0800285 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
286 "This subscription does not support UCE.");
287 }
James.cf Lin99a360d2020-11-04 10:48:37 +0800288 uceCtrlManager.requestCapabilities(contactNumbers, c);
289 } catch (ImsException e) {
290 throw new ServiceSpecificException(e.getCode(), e.getMessage());
Brad Ebingera68a4972020-01-30 17:31:23 -0800291 } finally {
292 Binder.restoreCallingIdentity(token);
Brad Ebinger1aa94992020-01-22 14:17:23 -0800293 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800294 }
295
296 @Override
James.cf Linbcdf8b32021-01-14 16:44:13 +0800297 public void requestAvailability(int subId, String callingPackage,
James.cf Lin64e91212020-10-30 01:09:52 +0800298 String callingFeatureId, Uri contactNumber, IRcsUceControllerCallback c) {
James.cf Lin051dd252021-01-21 03:30:54 +0800299 enforceAccessUserCapabilityExchangePermission("requestAvailability");
300 enforceReadContactsPermission("requestAvailability");
301 if (!isCallingProcessInForeground(Binder.getCallingUid())) {
302 throw new SecurityException("The caller is not in the foreground.");
303 }
Brad Ebingera68a4972020-01-30 17:31:23 -0800304 final long token = Binder.clearCallingIdentity();
305 try {
James.cf Lin99a360d2020-11-04 10:48:37 +0800306 UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
307 UceControllerManager.class);
308 if (uceCtrlManager == null) {
Brad Ebingera68a4972020-01-30 17:31:23 -0800309 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
310 "This subscription does not support UCE.");
311 }
James.cf Lin99a360d2020-11-04 10:48:37 +0800312 uceCtrlManager.requestNetworkAvailability(contactNumber, c);
313 } catch (ImsException e) {
314 throw new ServiceSpecificException(e.getCode(), e.getMessage());
315 } finally {
316 Binder.restoreCallingIdentity(token);
317 }
318 }
319
320 @Override
321 public @PublishState int getUcePublishState(int subId) {
322 enforceReadPrivilegedPermission("getUcePublishState");
323 final long token = Binder.clearCallingIdentity();
324 try {
325 UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
326 UceControllerManager.class);
327 if (uceCtrlManager == null) {
328 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
329 "This subscription does not support UCE.");
330 }
331 return uceCtrlManager.getUcePublishState();
332 } catch (ImsException e) {
333 throw new ServiceSpecificException(e.getCode(), e.getMessage());
334 } finally {
335 Binder.restoreCallingIdentity(token);
336 }
337 }
338
339 @Override
340 public void registerUcePublishStateCallback(int subId, IRcsUcePublishStateCallback c) {
341 enforceReadPrivilegedPermission("registerUcePublishStateCallback");
342 final long token = Binder.clearCallingIdentity();
343 try {
344 UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
345 UceControllerManager.class);
346 if (uceCtrlManager == null) {
347 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
348 "This subscription does not support UCE.");
349 }
350 uceCtrlManager.registerPublishStateCallback(c);
351 } catch (ImsException e) {
352 throw new ServiceSpecificException(e.getCode(), e.getMessage());
353 } finally {
354 Binder.restoreCallingIdentity(token);
355 }
356 }
357
358 @Override
359 public void unregisterUcePublishStateCallback(int subId, IRcsUcePublishStateCallback c) {
360 enforceReadPrivilegedPermission("unregisterUcePublishStateCallback");
361 final long token = Binder.clearCallingIdentity();
362 try {
363 UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
364 UceControllerManager.class);
365 if (uceCtrlManager == null) {
366 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
367 "This subscription does not support UCE.");
368 }
369 uceCtrlManager.unregisterPublishStateCallback(c);
Brad Ebingera68a4972020-01-30 17:31:23 -0800370 } finally {
371 Binder.restoreCallingIdentity(token);
Brad Ebinger1aa94992020-01-22 14:17:23 -0800372 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800373 }
374
375 @Override
Brad Ebinger8b79edc2020-02-27 19:13:24 -0800376 public boolean isUceSettingEnabled(int subId, String callingPackage, String callingFeatureId) {
377 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
378 mApp, subId, callingPackage, callingFeatureId, "isUceSettingEnabled")) {
379 Log.w(TAG, "isUceSettingEnabled: READ_PHONE_STATE app op disabled when accessing "
380 + "isUceSettingEnabled");
381 return false;
382 }
383 final long token = Binder.clearCallingIdentity();
384 try {
385 return SubscriptionManager.getBooleanSubscriptionProperty(subId,
386 SubscriptionManager.IMS_RCS_UCE_ENABLED, false /*defaultValue*/, mApp);
387 } finally {
388 Binder.restoreCallingIdentity(token);
389 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800390 }
391
392 @Override
393 public void setUceSettingEnabled(int subId, boolean isEnabled) {
394 enforceModifyPermission();
Brad Ebinger8b79edc2020-02-27 19:13:24 -0800395 final long token = Binder.clearCallingIdentity();
396 try {
397 SubscriptionManager.setSubscriptionProperty(subId,
398 SubscriptionManager.IMS_RCS_UCE_ENABLED, (isEnabled ? "1" : "0"));
399 } finally {
400 Binder.restoreCallingIdentity(token);
401 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800402 }
403
Brad Ebingerb989c7c2020-09-23 17:03:48 -0700404 @Override
405 public boolean isSipDelegateSupported(int subId) {
Brad Ebinger4df7e242021-02-17 23:23:21 +0000406 TelephonyPermissions.enforceAnyPermissionGranted(mApp, Binder.getCallingUid(),
407 "isSipDelegateSupported",
408 Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION,
409 Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
Brad Ebinger49a72b42021-01-29 00:55:24 +0000410 if (!isImsSingleRegistrationSupportedOnDevice()) {
411 return false;
412 }
Brad Ebingerb989c7c2020-09-23 17:03:48 -0700413 final long token = Binder.clearCallingIdentity();
414 try {
415 SipTransportController transport = getRcsFeatureController(subId).getFeature(
416 SipTransportController.class);
417 if (transport == null) {
418 return false;
419 }
420 return transport.isSupported(subId);
421 } catch (ImsException e) {
422 throw new ServiceSpecificException(e.getCode(), e.getMessage());
423 } catch (ServiceSpecificException e) {
424 if (e.errorCode == ImsException.CODE_ERROR_UNSUPPORTED_OPERATION) {
425 return false;
426 }
427 throw e;
428 } finally {
429 Binder.restoreCallingIdentity(token);
430 }
431 }
432
Brad Ebingeraf1e9832020-10-14 10:49:28 -0700433 @Override
Brad Ebinger63b6f5a2020-10-27 11:43:35 -0700434 public void createSipDelegate(int subId, DelegateRequest request, String packageName,
Brad Ebingeraf1e9832020-10-14 10:49:28 -0700435 ISipDelegateConnectionStateCallback delegateState,
436 ISipDelegateMessageCallback delegateMessage) {
Brad Ebinger4df7e242021-02-17 23:23:21 +0000437 enforceImsSingleRegistrationPermission("createSipDelegate");
Brad Ebinger49a72b42021-01-29 00:55:24 +0000438 if (!isImsSingleRegistrationSupportedOnDevice()) {
439 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
440 "SipDelegate creation is only supported for devices supporting IMS single "
441 + "registration");
442 }
Brad Ebinger63b6f5a2020-10-27 11:43:35 -0700443 if (!UserHandle.getUserHandleForUid(Binder.getCallingUid()).isSystem()) {
444 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
445 "SipDelegate creation is only available to primary user.");
446 }
447 try {
448 int remoteUid = mApp.getPackageManager().getPackageUid(packageName, 0 /*flags*/);
449 if (Binder.getCallingUid() != remoteUid) {
450 throw new SecurityException("passed in packageName does not match the caller");
451 }
452 } catch (PackageManager.NameNotFoundException e) {
453 throw new SecurityException("Passed in PackageName can not be found on device");
454 }
Brad Ebingeraf1e9832020-10-14 10:49:28 -0700455
456 final long identity = Binder.clearCallingIdentity();
457 SipTransportController transport = getRcsFeatureController(subId).getFeature(
458 SipTransportController.class);
459 if (transport == null) {
460 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
461 "This subscription does not support the creation of SIP delegates");
462 }
463 try {
Brad Ebinger63b6f5a2020-10-27 11:43:35 -0700464 transport.createSipDelegate(subId, request, packageName, delegateState,
465 delegateMessage);
Brad Ebingeraf1e9832020-10-14 10:49:28 -0700466 } catch (ImsException e) {
467 throw new ServiceSpecificException(e.getCode(), e.getMessage());
468 } finally {
469 Binder.restoreCallingIdentity(identity);
470 }
471 }
472
473 @Override
474 public void destroySipDelegate(int subId, ISipDelegate connection, int reason) {
Brad Ebinger4df7e242021-02-17 23:23:21 +0000475 enforceImsSingleRegistrationPermission("destroySipDelegate");
Brad Ebingeraf1e9832020-10-14 10:49:28 -0700476
477 final long identity = Binder.clearCallingIdentity();
478 try {
Brad Ebinger63b6f5a2020-10-27 11:43:35 -0700479 SipTransportController transport = getRcsFeatureController(subId).getFeature(
480 SipTransportController.class);
481 if (transport == null) {
482 return;
483 }
484 transport.destroySipDelegate(subId, connection, reason);
Brad Ebingeraf1e9832020-10-14 10:49:28 -0700485 } finally {
486 Binder.restoreCallingIdentity(identity);
487 }
488 }
489
Brad Ebinger36221382020-12-09 00:33:39 +0000490 @Override
491 public void triggerNetworkRegistration(int subId, ISipDelegate connection, int sipCode,
492 String sipReason) {
Brad Ebinger4df7e242021-02-17 23:23:21 +0000493 enforceImsSingleRegistrationPermission("triggerNetworkRegistration");
Brad Ebinger36221382020-12-09 00:33:39 +0000494
495 final long identity = Binder.clearCallingIdentity();
496 try {
497 SipTransportController transport = getRcsFeatureController(subId).getFeature(
498 SipTransportController.class);
499 if (transport == null) {
500 return;
501 }
502 transport.triggerFullNetworkRegistration(subId, connection, sipCode, sipReason);
503 } finally {
504 Binder.restoreCallingIdentity(identity);
505 }
506 }
507
James.cf Linaf3183c2019-10-24 00:59:00 +0800508 /**
Brad Ebingere3ae65a2020-09-11 12:45:11 -0700509 * Registers for updates to the RcsFeature connection through the IImsServiceFeatureCallback
510 * callback.
511 */
512 @Override
Brad Ebinger6366ce92020-10-01 13:51:05 -0700513 public void registerRcsFeatureCallback(int slotId, IImsServiceFeatureCallback callback) {
Brad Ebingere3ae65a2020-09-11 12:45:11 -0700514 enforceModifyPermission();
515
516 final long identity = Binder.clearCallingIdentity();
517 try {
518 if (mImsResolver == null) {
519 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
520 "Device does not support IMS");
521 }
Brad Ebinger6366ce92020-10-01 13:51:05 -0700522 mImsResolver.listenForFeature(slotId, ImsFeature.FEATURE_RCS, callback);
Brad Ebingere3ae65a2020-09-11 12:45:11 -0700523 } finally {
524 Binder.restoreCallingIdentity(identity);
525 }
526 }
Brad Ebinger6366ce92020-10-01 13:51:05 -0700527
Brad Ebingere3ae65a2020-09-11 12:45:11 -0700528 /**
529 * Unregister a previously registered IImsServiceFeatureCallback associated with an ImsFeature.
530 */
531 @Override
532 public void unregisterImsFeatureCallback(IImsServiceFeatureCallback callback) {
533 enforceModifyPermission();
534
535 final long identity = Binder.clearCallingIdentity();
536 try {
537 if (mImsResolver == null) return;
538 mImsResolver.unregisterImsFeatureCallback(callback);
539 } finally {
540 Binder.restoreCallingIdentity(identity);
541 }
542 }
543
544 /**
James.cf Linaf3183c2019-10-24 00:59:00 +0800545 * Make sure either called from same process as self (phone) or IPC caller has read privilege.
546 *
547 * @throws SecurityException if the caller does not have the required permission
548 */
549 private void enforceReadPrivilegedPermission(String message) {
550 mApp.enforceCallingOrSelfPermission(
551 android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, message);
552 }
553
554 /**
Brad Ebinger4df7e242021-02-17 23:23:21 +0000555 * @throws SecurityException if the caller does not have the required
556 * PERFORM_IMS_SINGLE_REGISTRATION permission.
557 */
558 private void enforceImsSingleRegistrationPermission(String message) {
559 mApp.enforceCallingOrSelfPermission(
560 Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION, message);
561 }
562
563 /**
James.cf Linaf3183c2019-10-24 00:59:00 +0800564 * Make sure the caller has the MODIFY_PHONE_STATE permission.
565 *
566 * @throws SecurityException if the caller does not have the required permission
567 */
568 private void enforceModifyPermission() {
569 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE, null);
570 }
James.cf Lincad981c2019-12-10 20:37:56 +0800571
572 /**
James.cf Lin051dd252021-01-21 03:30:54 +0800573 * Make sure the caller has the ACCESS_RCS_USER_CAPABILITY_EXCHANGE permission.
574 *
575 * @throws SecurityException if the caller does not have the required permission.
576 */
577 private void enforceAccessUserCapabilityExchangePermission(String message) {
578 mApp.enforceCallingOrSelfPermission(
579 android.Manifest.permission.ACCESS_RCS_USER_CAPABILITY_EXCHANGE, message);
580 }
581
582 /**
583 * Make sure the caller has the READ_CONTACTS permission.
584 *
585 * @throws SecurityException if the caller does not have the required permission.
586 */
587 private void enforceReadContactsPermission(String message) {
588 mApp.enforceCallingOrSelfPermission(
589 android.Manifest.permission.READ_CONTACTS, message);
590 }
591
592 /**
593 * Check if the calling process is in the foreground.
594 *
595 * @return true if the caller is in the foreground.
596 */
597 private boolean isCallingProcessInForeground(int uid) {
598 ActivityManager am = mApp.getSystemService(ActivityManager.class);
599 boolean isCallingProcessForeground = am != null
600 && am.getUidImportance(uid)
601 == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
602 return isCallingProcessForeground;
603 }
604
605 /**
James.cf Lindc2d5422019-12-31 14:40:25 +0800606 * Retrieve ImsPhone instance.
James.cf Lincad981c2019-12-10 20:37:56 +0800607 *
608 * @param subId the subscription ID
James.cf Lindc2d5422019-12-31 14:40:25 +0800609 * @return The ImsPhone instance
610 * @throws ServiceSpecificException if getting ImsPhone instance failed.
James.cf Lincad981c2019-12-10 20:37:56 +0800611 */
James.cf Lindc2d5422019-12-31 14:40:25 +0800612 private ImsPhone getImsPhone(int subId) {
613 if (!ImsManager.isImsSupportedOnDevice(mApp)) {
614 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
615 "IMS is not available on device.");
616 }
James.cf Lincad981c2019-12-10 20:37:56 +0800617 Phone phone = PhoneGlobals.getPhone(subId);
618 if (phone == null) {
619 throw new ServiceSpecificException(ImsException.CODE_ERROR_INVALID_SUBSCRIPTION,
620 "Invalid subscription Id: " + subId);
621 }
622 ImsPhone imsPhone = (ImsPhone) phone.getImsPhone();
623 if (imsPhone == null) {
James.cf Lindc2d5422019-12-31 14:40:25 +0800624 throw new ServiceSpecificException(ImsException.CODE_ERROR_SERVICE_UNAVAILABLE,
625 "Cannot find ImsPhone instance: " + subId);
626 }
627 return imsPhone;
628 }
629
630 /**
631 * Retrieve RcsFeatureManager instance.
632 *
633 * @param subId the subscription ID
634 * @return The RcsFeatureManager instance
635 * @throws ServiceSpecificException if getting RcsFeatureManager instance failed.
636 */
Brad Ebingera68a4972020-01-30 17:31:23 -0800637 private RcsFeatureController getRcsFeatureController(int subId) {
James.cf Lindc2d5422019-12-31 14:40:25 +0800638 if (!ImsManager.isImsSupportedOnDevice(mApp)) {
James.cf Lincad981c2019-12-10 20:37:56 +0800639 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
James.cf Lindc2d5422019-12-31 14:40:25 +0800640 "IMS is not available on device.");
641 }
Brad Ebingera68a4972020-01-30 17:31:23 -0800642 if (mRcsService == null) {
643 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
644 "IMS is not available on device.");
645 }
James.cf Lindc2d5422019-12-31 14:40:25 +0800646 Phone phone = PhoneGlobals.getPhone(subId);
647 if (phone == null) {
648 throw new ServiceSpecificException(ImsException.CODE_ERROR_INVALID_SUBSCRIPTION,
649 "Invalid subscription Id: " + subId);
650 }
Brad Ebingera68a4972020-01-30 17:31:23 -0800651 int slotId = phone.getPhoneId();
652 RcsFeatureController c = mRcsService.getFeatureController(slotId);
653 if (c == null) {
Brad Ebinger036dc9e2020-02-06 15:49:06 -0800654 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
655 "The requested operation is not supported for subId " + subId);
James.cf Lincad981c2019-12-10 20:37:56 +0800656 }
Brad Ebingera68a4972020-01-30 17:31:23 -0800657 return c;
James.cf Lincad981c2019-12-10 20:37:56 +0800658 }
James.cf Linc9f35a42020-01-15 02:35:22 +0800659
Brad Ebinger49a72b42021-01-29 00:55:24 +0000660 private boolean isImsSingleRegistrationSupportedOnDevice() {
661 return mSingleRegistrationOverride != null ? mSingleRegistrationOverride
662 : mApp.getPackageManager().hasSystemFeature(
663 PackageManager.FEATURE_TELEPHONY_IMS_SINGLE_REGISTRATION);
664 }
665
James.cf Linc9f35a42020-01-15 02:35:22 +0800666 void setRcsService(TelephonyRcsService rcsService) {
667 mRcsService = rcsService;
668 }
Brad Ebinger49a72b42021-01-29 00:55:24 +0000669
670 /**
671 * Override device RCS single registration support check for CTS testing or remove override
672 * if the Boolean is set to null.
673 */
674 void setDeviceSingleRegistrationSupportOverride(Boolean deviceOverrideValue) {
675 mSingleRegistrationOverride = deviceOverrideValue;
676 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800677}