blob: c91cc3b4d43516b9fbfd532ba09b5a96073e6acf [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 Ebinger63b6f5a2020-10-27 11:43:35 -070019import android.content.pm.PackageManager;
James.cf Linaf3183c2019-10-24 00:59:00 +080020import android.net.Uri;
James.cf Lincad981c2019-12-10 20:37:56 +080021import android.os.Binder;
22import android.os.RemoteException;
James.cf Lincad981c2019-12-10 20:37:56 +080023import android.os.ServiceSpecificException;
Brad Ebinger63b6f5a2020-10-27 11:43:35 -070024import android.os.UserHandle;
Brad Ebingerb7a866a2020-01-22 17:51:55 -080025import android.telephony.SubscriptionManager;
Peter Wangc035ce42020-01-08 21:00:22 -080026import android.telephony.TelephonyFrameworkInitializer;
Brad Ebingeraf1e9832020-10-14 10:49:28 -070027import android.telephony.ims.DelegateRequest;
James.cf Lincad981c2019-12-10 20:37:56 +080028import android.telephony.ims.ImsException;
James.cf Lin99a360d2020-11-04 10:48:37 +080029import android.telephony.ims.RcsUceAdapter.PublishState;
James.cf Lindc2d5422019-12-31 14:40:25 +080030import android.telephony.ims.RegistrationManager;
James.cf Linaf3183c2019-10-24 00:59:00 +080031import android.telephony.ims.aidl.IImsCapabilityCallback;
32import android.telephony.ims.aidl.IImsRcsController;
James.cf Lindc2d5422019-12-31 14:40:25 +080033import android.telephony.ims.aidl.IImsRegistrationCallback;
James.cf Linaf3183c2019-10-24 00:59:00 +080034import android.telephony.ims.aidl.IRcsUceControllerCallback;
James.cf Lincdad3862020-02-25 15:55:03 +080035import android.telephony.ims.aidl.IRcsUcePublishStateCallback;
Brad Ebingeraf1e9832020-10-14 10:49:28 -070036import android.telephony.ims.aidl.ISipDelegate;
37import android.telephony.ims.aidl.ISipDelegateConnectionStateCallback;
38import android.telephony.ims.aidl.ISipDelegateMessageCallback;
Brad Ebingere3ae65a2020-09-11 12:45:11 -070039import android.telephony.ims.feature.ImsFeature;
James.cf Linaf3183c2019-10-24 00:59:00 +080040import android.telephony.ims.feature.RcsFeature;
James.cf Lincad981c2019-12-10 20:37:56 +080041import android.telephony.ims.stub.ImsRegistrationImplBase;
James.cf Linaf3183c2019-10-24 00:59:00 +080042import android.util.Log;
43
James.cf Lindc2d5422019-12-31 14:40:25 +080044import com.android.ims.ImsManager;
Brad Ebingere3ae65a2020-09-11 12:45:11 -070045import com.android.ims.internal.IImsServiceFeatureCallback;
James.cf Lindc2d5422019-12-31 14:40:25 +080046import com.android.internal.telephony.IIntegerConsumer;
James.cf Lincad981c2019-12-10 20:37:56 +080047import com.android.internal.telephony.Phone;
Brad Ebinger8b79edc2020-02-27 19:13:24 -080048import com.android.internal.telephony.TelephonyPermissions;
Brad Ebingere3ae65a2020-09-11 12:45:11 -070049import com.android.internal.telephony.ims.ImsResolver;
James.cf Lincad981c2019-12-10 20:37:56 +080050import com.android.internal.telephony.imsphone.ImsPhone;
Brad Ebingera68a4972020-01-30 17:31:23 -080051import com.android.services.telephony.rcs.RcsFeatureController;
Brad Ebingerb989c7c2020-09-23 17:03:48 -070052import com.android.services.telephony.rcs.SipTransportController;
James.cf Linc9f35a42020-01-15 02:35:22 +080053import com.android.services.telephony.rcs.TelephonyRcsService;
James.cf Lin99a360d2020-11-04 10:48:37 +080054import com.android.services.telephony.rcs.UceControllerManager;
James.cf Lincad981c2019-12-10 20:37:56 +080055
James.cf Linaf3183c2019-10-24 00:59:00 +080056import java.util.List;
57
58/**
59 * Implementation of the IImsRcsController interface.
60 */
61public class ImsRcsController extends IImsRcsController.Stub {
62 private static final String TAG = "ImsRcsController";
63
64 /** The singleton instance. */
65 private static ImsRcsController sInstance;
66
67 private PhoneGlobals mApp;
James.cf Linc9f35a42020-01-15 02:35:22 +080068 private TelephonyRcsService mRcsService;
Brad Ebingere3ae65a2020-09-11 12:45:11 -070069 private ImsResolver mImsResolver;
Brad Ebinger49a72b42021-01-29 00:55:24 +000070 // set by shell cmd phone src set-device-enabled true/false
71 private Boolean mSingleRegistrationOverride;
James.cf Linaf3183c2019-10-24 00:59:00 +080072
73 /**
74 * Initialize the singleton ImsRcsController instance.
75 * This is only done once, at startup, from PhoneApp.onCreate().
76 */
77 static ImsRcsController init(PhoneGlobals app) {
78 synchronized (ImsRcsController.class) {
79 if (sInstance == null) {
80 sInstance = new ImsRcsController(app);
81 } else {
82 Log.wtf(TAG, "init() called multiple times! sInstance = " + sInstance);
83 }
84 return sInstance;
85 }
86 }
87
88 /** Private constructor; @see init() */
89 private ImsRcsController(PhoneGlobals app) {
90 Log.i(TAG, "ImsRcsController");
91 mApp = app;
Peter Wangc035ce42020-01-08 21:00:22 -080092 TelephonyFrameworkInitializer
93 .getTelephonyServiceManager().getTelephonyImsServiceRegisterer().register(this);
Brad Ebingere3ae65a2020-09-11 12:45:11 -070094 mImsResolver = mApp.getImsResolver();
James.cf Linaf3183c2019-10-24 00:59:00 +080095 }
96
James.cf Lincad981c2019-12-10 20:37:56 +080097 /**
Brad Ebingera68a4972020-01-30 17:31:23 -080098 * Register a {@link RegistrationManager.RegistrationCallback} to receive IMS network
99 * registration state.
James.cf Lindc2d5422019-12-31 14:40:25 +0800100 */
101 @Override
Brad Ebingera68a4972020-01-30 17:31:23 -0800102 public void registerImsRegistrationCallback(int subId, IImsRegistrationCallback callback) {
James.cf Lindc2d5422019-12-31 14:40:25 +0800103 enforceReadPrivilegedPermission("registerImsRegistrationCallback");
104 final long token = Binder.clearCallingIdentity();
105 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800106 getRcsFeatureController(subId).registerImsRegistrationCallback(subId, callback);
107 } catch (ImsException e) {
James.cf Lindc2d5422019-12-31 14:40:25 +0800108 Log.e(TAG, "registerImsRegistrationCallback: sudId=" + subId + ", " + e.getMessage());
109 throw new ServiceSpecificException(e.getCode());
110 } finally {
111 Binder.restoreCallingIdentity(token);
112 }
113 }
114
115 /**
Brad Ebingera68a4972020-01-30 17:31:23 -0800116 * Removes an existing {@link RegistrationManager.RegistrationCallback}.
James.cf Lindc2d5422019-12-31 14:40:25 +0800117 */
118 @Override
119 public void unregisterImsRegistrationCallback(int subId, IImsRegistrationCallback callback) {
120 enforceReadPrivilegedPermission("unregisterImsRegistrationCallback");
121 final long token = Binder.clearCallingIdentity();
122 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800123 getRcsFeatureController(subId).unregisterImsRegistrationCallback(subId, callback);
James.cf Lindc2d5422019-12-31 14:40:25 +0800124 } catch (ServiceSpecificException e) {
125 Log.e(TAG, "unregisterImsRegistrationCallback: error=" + e.errorCode);
126 } finally {
127 Binder.restoreCallingIdentity(token);
128 }
129 }
130
131 /**
132 * Get the IMS service registration state for the RcsFeature associated with this sub id.
133 */
134 @Override
135 public void getImsRcsRegistrationState(int subId, IIntegerConsumer consumer) {
136 enforceReadPrivilegedPermission("getImsRcsRegistrationState");
137 final long token = Binder.clearCallingIdentity();
138 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800139 getRcsFeatureController(subId).getRegistrationState(regState -> {
James.cf Lindc2d5422019-12-31 14:40:25 +0800140 try {
141 consumer.accept((regState == null)
142 ? RegistrationManager.REGISTRATION_STATE_NOT_REGISTERED : regState);
143 } catch (RemoteException e) {
144 Log.w(TAG, "getImsRcsRegistrationState: callback is not available.");
145 }
146 });
147 } finally {
148 Binder.restoreCallingIdentity(token);
149 }
150 }
151
152 /**
153 * Gets the Transport Type associated with the current IMS RCS registration.
154 */
155 @Override
156 public void getImsRcsRegistrationTransportType(int subId, IIntegerConsumer consumer) {
157 enforceReadPrivilegedPermission("getImsRcsRegistrationTransportType");
158 final long token = Binder.clearCallingIdentity();
159 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800160 getRcsFeatureController(subId).getRegistrationTech(regTech -> {
James.cf Lindc2d5422019-12-31 14:40:25 +0800161 // Convert registration tech from ImsRegistrationImplBase -> RegistrationManager
162 int regTechConverted = (regTech == null)
163 ? ImsRegistrationImplBase.REGISTRATION_TECH_NONE : regTech;
164 regTechConverted = RegistrationManager.IMS_REG_TO_ACCESS_TYPE_MAP.get(
165 regTechConverted);
166 try {
167 consumer.accept(regTechConverted);
168 } catch (RemoteException e) {
169 Log.w(TAG, "getImsRcsRegistrationTransportType: callback is not available.");
170 }
171 });
172 } finally {
173 Binder.restoreCallingIdentity(token);
174 }
175 }
176
177 /**
James.cf Lincad981c2019-12-10 20:37:56 +0800178 * Register a capability callback which will provide RCS availability updates for the
179 * subscription specified.
180 *
181 * @param subId the subscription ID
182 * @param callback The ImsCapabilityCallback to be registered.
183 */
James.cf Linaf3183c2019-10-24 00:59:00 +0800184 @Override
Brad Ebingera68a4972020-01-30 17:31:23 -0800185 public void registerRcsAvailabilityCallback(int subId, IImsCapabilityCallback callback) {
James.cf Linaf3183c2019-10-24 00:59:00 +0800186 enforceReadPrivilegedPermission("registerRcsAvailabilityCallback");
James.cf Lincad981c2019-12-10 20:37:56 +0800187 final long token = Binder.clearCallingIdentity();
188 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800189 getRcsFeatureController(subId).registerRcsAvailabilityCallback(subId, callback);
190 } catch (ImsException e) {
James.cf Lincad981c2019-12-10 20:37:56 +0800191 Log.e(TAG, "registerRcsAvailabilityCallback: sudId=" + subId + ", " + e.getMessage());
192 throw new ServiceSpecificException(e.getCode());
193 } finally {
194 Binder.restoreCallingIdentity(token);
195 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800196 }
197
James.cf Lincad981c2019-12-10 20:37:56 +0800198 /**
199 * Remove the registered capability callback.
200 *
201 * @param subId the subscription ID
202 * @param callback The ImsCapabilityCallback to be removed.
203 */
James.cf Linaf3183c2019-10-24 00:59:00 +0800204 @Override
James.cf Lincad981c2019-12-10 20:37:56 +0800205 public void unregisterRcsAvailabilityCallback(int subId, IImsCapabilityCallback callback) {
James.cf Linaf3183c2019-10-24 00:59:00 +0800206 enforceReadPrivilegedPermission("unregisterRcsAvailabilityCallback");
James.cf Lincad981c2019-12-10 20:37:56 +0800207 final long token = Binder.clearCallingIdentity();
208 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800209 getRcsFeatureController(subId).unregisterRcsAvailabilityCallback(subId, callback);
James.cf Lincad981c2019-12-10 20:37:56 +0800210 } finally {
211 Binder.restoreCallingIdentity(token);
212 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800213 }
214
James.cf Lincad981c2019-12-10 20:37:56 +0800215 /**
216 * Query for the capability of an IMS RCS service
217 *
218 * @param subId the subscription ID
219 * @param capability the RCS capability to query.
220 * @param radioTech the radio tech that this capability failed for
221 * @return true if the RCS capability is capable for this subscription, false otherwise.
222 */
James.cf Linaf3183c2019-10-24 00:59:00 +0800223 @Override
224 public boolean isCapable(int subId,
James.cf Lincad981c2019-12-10 20:37:56 +0800225 @RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability,
226 @ImsRegistrationImplBase.ImsRegistrationTech int radioTech) {
James.cf Linaf3183c2019-10-24 00:59:00 +0800227 enforceReadPrivilegedPermission("isCapable");
James.cf Lincad981c2019-12-10 20:37:56 +0800228 final long token = Binder.clearCallingIdentity();
229 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800230 return getRcsFeatureController(subId).isCapable(capability, radioTech);
231 } catch (ImsException e) {
James.cf Lincad981c2019-12-10 20:37:56 +0800232 Log.e(TAG, "isCapable: sudId=" + subId
233 + ", capability=" + capability + ", " + e.getMessage());
234 return false;
235 } finally {
236 Binder.restoreCallingIdentity(token);
237 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800238 }
239
James.cf Lincad981c2019-12-10 20:37:56 +0800240 /**
241 * Query the availability of an IMS RCS capability.
242 *
243 * @param subId the subscription ID
244 * @param capability the RCS capability to query.
245 * @return true if the RCS capability is currently available for the associated subscription,
246 * false otherwise.
247 */
James.cf Linaf3183c2019-10-24 00:59:00 +0800248 @Override
249 public boolean isAvailable(int subId,
250 @RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability) {
251 enforceReadPrivilegedPermission("isAvailable");
James.cf Lincad981c2019-12-10 20:37:56 +0800252 final long token = Binder.clearCallingIdentity();
253 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800254 return getRcsFeatureController(subId).isAvailable(capability);
255 } catch (ImsException e) {
James.cf Lincad981c2019-12-10 20:37:56 +0800256 Log.e(TAG, "isAvailable: sudId=" + subId
257 + ", capability=" + capability + ", " + e.getMessage());
258 return false;
259 } finally {
260 Binder.restoreCallingIdentity(token);
261 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800262 }
263
264 @Override
Brad Ebinger8b79edc2020-02-27 19:13:24 -0800265 public void requestCapabilities(int subId, String callingPackage, String callingFeatureId,
266 List<Uri> contactNumbers, IRcsUceControllerCallback c) {
James.cf Linaf3183c2019-10-24 00:59:00 +0800267 enforceReadPrivilegedPermission("requestCapabilities");
Brad Ebingera68a4972020-01-30 17:31:23 -0800268 final long token = Binder.clearCallingIdentity();
269 try {
James.cf Lin99a360d2020-11-04 10:48:37 +0800270 UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
271 UceControllerManager.class);
272 if (uceCtrlManager == null) {
Brad Ebingera68a4972020-01-30 17:31:23 -0800273 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
274 "This subscription does not support UCE.");
275 }
James.cf Lin99a360d2020-11-04 10:48:37 +0800276 uceCtrlManager.requestCapabilities(contactNumbers, c);
277 } catch (ImsException e) {
278 throw new ServiceSpecificException(e.getCode(), e.getMessage());
Brad Ebingera68a4972020-01-30 17:31:23 -0800279 } finally {
280 Binder.restoreCallingIdentity(token);
Brad Ebinger1aa94992020-01-22 14:17:23 -0800281 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800282 }
283
284 @Override
James.cf Linbcdf8b32021-01-14 16:44:13 +0800285 public void requestAvailability(int subId, String callingPackage,
James.cf Lin64e91212020-10-30 01:09:52 +0800286 String callingFeatureId, Uri contactNumber, IRcsUceControllerCallback c) {
James.cf Linbcdf8b32021-01-14 16:44:13 +0800287 enforceReadPrivilegedPermission("requestAvailability");
Brad Ebingera68a4972020-01-30 17:31:23 -0800288 final long token = Binder.clearCallingIdentity();
289 try {
James.cf Lin99a360d2020-11-04 10:48:37 +0800290 UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
291 UceControllerManager.class);
292 if (uceCtrlManager == null) {
Brad Ebingera68a4972020-01-30 17:31:23 -0800293 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
294 "This subscription does not support UCE.");
295 }
James.cf Lin99a360d2020-11-04 10:48:37 +0800296 uceCtrlManager.requestNetworkAvailability(contactNumber, c);
297 } catch (ImsException e) {
298 throw new ServiceSpecificException(e.getCode(), e.getMessage());
299 } finally {
300 Binder.restoreCallingIdentity(token);
301 }
302 }
303
304 @Override
305 public @PublishState int getUcePublishState(int subId) {
306 enforceReadPrivilegedPermission("getUcePublishState");
307 final long token = Binder.clearCallingIdentity();
308 try {
309 UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
310 UceControllerManager.class);
311 if (uceCtrlManager == null) {
312 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
313 "This subscription does not support UCE.");
314 }
315 return uceCtrlManager.getUcePublishState();
316 } catch (ImsException e) {
317 throw new ServiceSpecificException(e.getCode(), e.getMessage());
318 } finally {
319 Binder.restoreCallingIdentity(token);
320 }
321 }
322
323 @Override
324 public void registerUcePublishStateCallback(int subId, IRcsUcePublishStateCallback c) {
325 enforceReadPrivilegedPermission("registerUcePublishStateCallback");
326 final long token = Binder.clearCallingIdentity();
327 try {
328 UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
329 UceControllerManager.class);
330 if (uceCtrlManager == null) {
331 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
332 "This subscription does not support UCE.");
333 }
334 uceCtrlManager.registerPublishStateCallback(c);
335 } catch (ImsException e) {
336 throw new ServiceSpecificException(e.getCode(), e.getMessage());
337 } finally {
338 Binder.restoreCallingIdentity(token);
339 }
340 }
341
342 @Override
343 public void unregisterUcePublishStateCallback(int subId, IRcsUcePublishStateCallback c) {
344 enforceReadPrivilegedPermission("unregisterUcePublishStateCallback");
345 final long token = Binder.clearCallingIdentity();
346 try {
347 UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
348 UceControllerManager.class);
349 if (uceCtrlManager == null) {
350 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
351 "This subscription does not support UCE.");
352 }
353 uceCtrlManager.unregisterPublishStateCallback(c);
Brad Ebingera68a4972020-01-30 17:31:23 -0800354 } finally {
355 Binder.restoreCallingIdentity(token);
Brad Ebinger1aa94992020-01-22 14:17:23 -0800356 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800357 }
358
359 @Override
Brad Ebinger8b79edc2020-02-27 19:13:24 -0800360 public boolean isUceSettingEnabled(int subId, String callingPackage, String callingFeatureId) {
361 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
362 mApp, subId, callingPackage, callingFeatureId, "isUceSettingEnabled")) {
363 Log.w(TAG, "isUceSettingEnabled: READ_PHONE_STATE app op disabled when accessing "
364 + "isUceSettingEnabled");
365 return false;
366 }
367 final long token = Binder.clearCallingIdentity();
368 try {
369 return SubscriptionManager.getBooleanSubscriptionProperty(subId,
370 SubscriptionManager.IMS_RCS_UCE_ENABLED, false /*defaultValue*/, mApp);
371 } finally {
372 Binder.restoreCallingIdentity(token);
373 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800374 }
375
376 @Override
377 public void setUceSettingEnabled(int subId, boolean isEnabled) {
378 enforceModifyPermission();
Brad Ebinger8b79edc2020-02-27 19:13:24 -0800379 final long token = Binder.clearCallingIdentity();
380 try {
381 SubscriptionManager.setSubscriptionProperty(subId,
382 SubscriptionManager.IMS_RCS_UCE_ENABLED, (isEnabled ? "1" : "0"));
383 } finally {
384 Binder.restoreCallingIdentity(token);
385 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800386 }
387
Brad Ebingerb989c7c2020-09-23 17:03:48 -0700388 @Override
389 public boolean isSipDelegateSupported(int subId) {
390 enforceReadPrivilegedPermission("isSipDelegateSupported");
Brad Ebinger49a72b42021-01-29 00:55:24 +0000391 if (!isImsSingleRegistrationSupportedOnDevice()) {
392 return false;
393 }
Brad Ebingerb989c7c2020-09-23 17:03:48 -0700394 final long token = Binder.clearCallingIdentity();
395 try {
396 SipTransportController transport = getRcsFeatureController(subId).getFeature(
397 SipTransportController.class);
398 if (transport == null) {
399 return false;
400 }
401 return transport.isSupported(subId);
402 } catch (ImsException e) {
403 throw new ServiceSpecificException(e.getCode(), e.getMessage());
404 } catch (ServiceSpecificException e) {
405 if (e.errorCode == ImsException.CODE_ERROR_UNSUPPORTED_OPERATION) {
406 return false;
407 }
408 throw e;
409 } finally {
410 Binder.restoreCallingIdentity(token);
411 }
412 }
413
Brad Ebingeraf1e9832020-10-14 10:49:28 -0700414 @Override
Brad Ebinger63b6f5a2020-10-27 11:43:35 -0700415 public void createSipDelegate(int subId, DelegateRequest request, String packageName,
Brad Ebingeraf1e9832020-10-14 10:49:28 -0700416 ISipDelegateConnectionStateCallback delegateState,
417 ISipDelegateMessageCallback delegateMessage) {
418 enforceModifyPermission();
Brad Ebinger49a72b42021-01-29 00:55:24 +0000419 if (!isImsSingleRegistrationSupportedOnDevice()) {
420 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
421 "SipDelegate creation is only supported for devices supporting IMS single "
422 + "registration");
423 }
Brad Ebinger63b6f5a2020-10-27 11:43:35 -0700424 if (!UserHandle.getUserHandleForUid(Binder.getCallingUid()).isSystem()) {
425 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
426 "SipDelegate creation is only available to primary user.");
427 }
428 try {
429 int remoteUid = mApp.getPackageManager().getPackageUid(packageName, 0 /*flags*/);
430 if (Binder.getCallingUid() != remoteUid) {
431 throw new SecurityException("passed in packageName does not match the caller");
432 }
433 } catch (PackageManager.NameNotFoundException e) {
434 throw new SecurityException("Passed in PackageName can not be found on device");
435 }
Brad Ebingeraf1e9832020-10-14 10:49:28 -0700436
437 final long identity = Binder.clearCallingIdentity();
438 SipTransportController transport = getRcsFeatureController(subId).getFeature(
439 SipTransportController.class);
440 if (transport == null) {
441 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
442 "This subscription does not support the creation of SIP delegates");
443 }
444 try {
Brad Ebinger63b6f5a2020-10-27 11:43:35 -0700445 transport.createSipDelegate(subId, request, packageName, delegateState,
446 delegateMessage);
Brad Ebingeraf1e9832020-10-14 10:49:28 -0700447 } catch (ImsException e) {
448 throw new ServiceSpecificException(e.getCode(), e.getMessage());
449 } finally {
450 Binder.restoreCallingIdentity(identity);
451 }
452 }
453
454 @Override
455 public void destroySipDelegate(int subId, ISipDelegate connection, int reason) {
456 enforceModifyPermission();
457
458 final long identity = Binder.clearCallingIdentity();
459 try {
Brad Ebinger63b6f5a2020-10-27 11:43:35 -0700460 SipTransportController transport = getRcsFeatureController(subId).getFeature(
461 SipTransportController.class);
462 if (transport == null) {
463 return;
464 }
465 transport.destroySipDelegate(subId, connection, reason);
Brad Ebingeraf1e9832020-10-14 10:49:28 -0700466 } finally {
467 Binder.restoreCallingIdentity(identity);
468 }
469 }
470
Brad Ebinger36221382020-12-09 00:33:39 +0000471 @Override
472 public void triggerNetworkRegistration(int subId, ISipDelegate connection, int sipCode,
473 String sipReason) {
474 enforceModifyPermission();
475
476 final long identity = Binder.clearCallingIdentity();
477 try {
478 SipTransportController transport = getRcsFeatureController(subId).getFeature(
479 SipTransportController.class);
480 if (transport == null) {
481 return;
482 }
483 transport.triggerFullNetworkRegistration(subId, connection, sipCode, sipReason);
484 } finally {
485 Binder.restoreCallingIdentity(identity);
486 }
487 }
488
James.cf Linaf3183c2019-10-24 00:59:00 +0800489 /**
Brad Ebingere3ae65a2020-09-11 12:45:11 -0700490 * Registers for updates to the RcsFeature connection through the IImsServiceFeatureCallback
491 * callback.
492 */
493 @Override
Brad Ebinger6366ce92020-10-01 13:51:05 -0700494 public void registerRcsFeatureCallback(int slotId, IImsServiceFeatureCallback callback) {
Brad Ebingere3ae65a2020-09-11 12:45:11 -0700495 enforceModifyPermission();
496
497 final long identity = Binder.clearCallingIdentity();
498 try {
499 if (mImsResolver == null) {
500 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
501 "Device does not support IMS");
502 }
Brad Ebinger6366ce92020-10-01 13:51:05 -0700503 mImsResolver.listenForFeature(slotId, ImsFeature.FEATURE_RCS, callback);
Brad Ebingere3ae65a2020-09-11 12:45:11 -0700504 } finally {
505 Binder.restoreCallingIdentity(identity);
506 }
507 }
Brad Ebinger6366ce92020-10-01 13:51:05 -0700508
Brad Ebingere3ae65a2020-09-11 12:45:11 -0700509 /**
510 * Unregister a previously registered IImsServiceFeatureCallback associated with an ImsFeature.
511 */
512 @Override
513 public void unregisterImsFeatureCallback(IImsServiceFeatureCallback callback) {
514 enforceModifyPermission();
515
516 final long identity = Binder.clearCallingIdentity();
517 try {
518 if (mImsResolver == null) return;
519 mImsResolver.unregisterImsFeatureCallback(callback);
520 } finally {
521 Binder.restoreCallingIdentity(identity);
522 }
523 }
524
525 /**
James.cf Linaf3183c2019-10-24 00:59:00 +0800526 * Make sure either called from same process as self (phone) or IPC caller has read privilege.
527 *
528 * @throws SecurityException if the caller does not have the required permission
529 */
530 private void enforceReadPrivilegedPermission(String message) {
531 mApp.enforceCallingOrSelfPermission(
532 android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, message);
533 }
534
535 /**
536 * Make sure the caller has the MODIFY_PHONE_STATE permission.
537 *
538 * @throws SecurityException if the caller does not have the required permission
539 */
540 private void enforceModifyPermission() {
541 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE, null);
542 }
James.cf Lincad981c2019-12-10 20:37:56 +0800543
544 /**
James.cf Lindc2d5422019-12-31 14:40:25 +0800545 * Retrieve ImsPhone instance.
James.cf Lincad981c2019-12-10 20:37:56 +0800546 *
547 * @param subId the subscription ID
James.cf Lindc2d5422019-12-31 14:40:25 +0800548 * @return The ImsPhone instance
549 * @throws ServiceSpecificException if getting ImsPhone instance failed.
James.cf Lincad981c2019-12-10 20:37:56 +0800550 */
James.cf Lindc2d5422019-12-31 14:40:25 +0800551 private ImsPhone getImsPhone(int subId) {
552 if (!ImsManager.isImsSupportedOnDevice(mApp)) {
553 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
554 "IMS is not available on device.");
555 }
James.cf Lincad981c2019-12-10 20:37:56 +0800556 Phone phone = PhoneGlobals.getPhone(subId);
557 if (phone == null) {
558 throw new ServiceSpecificException(ImsException.CODE_ERROR_INVALID_SUBSCRIPTION,
559 "Invalid subscription Id: " + subId);
560 }
561 ImsPhone imsPhone = (ImsPhone) phone.getImsPhone();
562 if (imsPhone == null) {
James.cf Lindc2d5422019-12-31 14:40:25 +0800563 throw new ServiceSpecificException(ImsException.CODE_ERROR_SERVICE_UNAVAILABLE,
564 "Cannot find ImsPhone instance: " + subId);
565 }
566 return imsPhone;
567 }
568
569 /**
570 * Retrieve RcsFeatureManager instance.
571 *
572 * @param subId the subscription ID
573 * @return The RcsFeatureManager instance
574 * @throws ServiceSpecificException if getting RcsFeatureManager instance failed.
575 */
Brad Ebingera68a4972020-01-30 17:31:23 -0800576 private RcsFeatureController getRcsFeatureController(int subId) {
James.cf Lindc2d5422019-12-31 14:40:25 +0800577 if (!ImsManager.isImsSupportedOnDevice(mApp)) {
James.cf Lincad981c2019-12-10 20:37:56 +0800578 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
James.cf Lindc2d5422019-12-31 14:40:25 +0800579 "IMS is not available on device.");
580 }
Brad Ebingera68a4972020-01-30 17:31:23 -0800581 if (mRcsService == null) {
582 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
583 "IMS is not available on device.");
584 }
James.cf Lindc2d5422019-12-31 14:40:25 +0800585 Phone phone = PhoneGlobals.getPhone(subId);
586 if (phone == null) {
587 throw new ServiceSpecificException(ImsException.CODE_ERROR_INVALID_SUBSCRIPTION,
588 "Invalid subscription Id: " + subId);
589 }
Brad Ebingera68a4972020-01-30 17:31:23 -0800590 int slotId = phone.getPhoneId();
591 RcsFeatureController c = mRcsService.getFeatureController(slotId);
592 if (c == null) {
Brad Ebinger036dc9e2020-02-06 15:49:06 -0800593 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
594 "The requested operation is not supported for subId " + subId);
James.cf Lincad981c2019-12-10 20:37:56 +0800595 }
Brad Ebingera68a4972020-01-30 17:31:23 -0800596 return c;
James.cf Lincad981c2019-12-10 20:37:56 +0800597 }
James.cf Linc9f35a42020-01-15 02:35:22 +0800598
Brad Ebinger49a72b42021-01-29 00:55:24 +0000599 private boolean isImsSingleRegistrationSupportedOnDevice() {
600 return mSingleRegistrationOverride != null ? mSingleRegistrationOverride
601 : mApp.getPackageManager().hasSystemFeature(
602 PackageManager.FEATURE_TELEPHONY_IMS_SINGLE_REGISTRATION);
603 }
604
James.cf Linc9f35a42020-01-15 02:35:22 +0800605 void setRcsService(TelephonyRcsService rcsService) {
606 mRcsService = rcsService;
607 }
Brad Ebinger49a72b42021-01-29 00:55:24 +0000608
609 /**
610 * Override device RCS single registration support check for CTS testing or remove override
611 * if the Boolean is set to null.
612 */
613 void setDeviceSingleRegistrationSupportOverride(Boolean deviceOverrideValue) {
614 mSingleRegistrationOverride = deviceOverrideValue;
615 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800616}