blob: 2c87f7c428885708d70ed43d3883da3f26641f0d [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;
James.cf Linaf3183c2019-10-24 00:59:00 +080070
71 /**
72 * Initialize the singleton ImsRcsController instance.
73 * This is only done once, at startup, from PhoneApp.onCreate().
74 */
75 static ImsRcsController init(PhoneGlobals app) {
76 synchronized (ImsRcsController.class) {
77 if (sInstance == null) {
78 sInstance = new ImsRcsController(app);
79 } else {
80 Log.wtf(TAG, "init() called multiple times! sInstance = " + sInstance);
81 }
82 return sInstance;
83 }
84 }
85
86 /** Private constructor; @see init() */
87 private ImsRcsController(PhoneGlobals app) {
88 Log.i(TAG, "ImsRcsController");
89 mApp = app;
Peter Wangc035ce42020-01-08 21:00:22 -080090 TelephonyFrameworkInitializer
91 .getTelephonyServiceManager().getTelephonyImsServiceRegisterer().register(this);
Brad Ebingere3ae65a2020-09-11 12:45:11 -070092 mImsResolver = mApp.getImsResolver();
James.cf Linaf3183c2019-10-24 00:59:00 +080093 }
94
James.cf Lincad981c2019-12-10 20:37:56 +080095 /**
Brad Ebingera68a4972020-01-30 17:31:23 -080096 * Register a {@link RegistrationManager.RegistrationCallback} to receive IMS network
97 * registration state.
James.cf Lindc2d5422019-12-31 14:40:25 +080098 */
99 @Override
Brad Ebingera68a4972020-01-30 17:31:23 -0800100 public void registerImsRegistrationCallback(int subId, IImsRegistrationCallback callback) {
James.cf Lindc2d5422019-12-31 14:40:25 +0800101 enforceReadPrivilegedPermission("registerImsRegistrationCallback");
102 final long token = Binder.clearCallingIdentity();
103 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800104 getRcsFeatureController(subId).registerImsRegistrationCallback(subId, callback);
105 } catch (ImsException e) {
James.cf Lindc2d5422019-12-31 14:40:25 +0800106 Log.e(TAG, "registerImsRegistrationCallback: sudId=" + subId + ", " + e.getMessage());
107 throw new ServiceSpecificException(e.getCode());
108 } finally {
109 Binder.restoreCallingIdentity(token);
110 }
111 }
112
113 /**
Brad Ebingera68a4972020-01-30 17:31:23 -0800114 * Removes an existing {@link RegistrationManager.RegistrationCallback}.
James.cf Lindc2d5422019-12-31 14:40:25 +0800115 */
116 @Override
117 public void unregisterImsRegistrationCallback(int subId, IImsRegistrationCallback callback) {
118 enforceReadPrivilegedPermission("unregisterImsRegistrationCallback");
119 final long token = Binder.clearCallingIdentity();
120 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800121 getRcsFeatureController(subId).unregisterImsRegistrationCallback(subId, callback);
James.cf Lindc2d5422019-12-31 14:40:25 +0800122 } catch (ServiceSpecificException e) {
123 Log.e(TAG, "unregisterImsRegistrationCallback: error=" + e.errorCode);
124 } finally {
125 Binder.restoreCallingIdentity(token);
126 }
127 }
128
129 /**
130 * Get the IMS service registration state for the RcsFeature associated with this sub id.
131 */
132 @Override
133 public void getImsRcsRegistrationState(int subId, IIntegerConsumer consumer) {
134 enforceReadPrivilegedPermission("getImsRcsRegistrationState");
135 final long token = Binder.clearCallingIdentity();
136 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800137 getRcsFeatureController(subId).getRegistrationState(regState -> {
James.cf Lindc2d5422019-12-31 14:40:25 +0800138 try {
139 consumer.accept((regState == null)
140 ? RegistrationManager.REGISTRATION_STATE_NOT_REGISTERED : regState);
141 } catch (RemoteException e) {
142 Log.w(TAG, "getImsRcsRegistrationState: callback is not available.");
143 }
144 });
145 } finally {
146 Binder.restoreCallingIdentity(token);
147 }
148 }
149
150 /**
151 * Gets the Transport Type associated with the current IMS RCS registration.
152 */
153 @Override
154 public void getImsRcsRegistrationTransportType(int subId, IIntegerConsumer consumer) {
155 enforceReadPrivilegedPermission("getImsRcsRegistrationTransportType");
156 final long token = Binder.clearCallingIdentity();
157 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800158 getRcsFeatureController(subId).getRegistrationTech(regTech -> {
James.cf Lindc2d5422019-12-31 14:40:25 +0800159 // Convert registration tech from ImsRegistrationImplBase -> RegistrationManager
160 int regTechConverted = (regTech == null)
161 ? ImsRegistrationImplBase.REGISTRATION_TECH_NONE : regTech;
162 regTechConverted = RegistrationManager.IMS_REG_TO_ACCESS_TYPE_MAP.get(
163 regTechConverted);
164 try {
165 consumer.accept(regTechConverted);
166 } catch (RemoteException e) {
167 Log.w(TAG, "getImsRcsRegistrationTransportType: callback is not available.");
168 }
169 });
170 } finally {
171 Binder.restoreCallingIdentity(token);
172 }
173 }
174
175 /**
James.cf Lincad981c2019-12-10 20:37:56 +0800176 * Register a capability callback which will provide RCS availability updates for the
177 * subscription specified.
178 *
179 * @param subId the subscription ID
180 * @param callback The ImsCapabilityCallback to be registered.
181 */
James.cf Linaf3183c2019-10-24 00:59:00 +0800182 @Override
Brad Ebingera68a4972020-01-30 17:31:23 -0800183 public void registerRcsAvailabilityCallback(int subId, IImsCapabilityCallback callback) {
James.cf Linaf3183c2019-10-24 00:59:00 +0800184 enforceReadPrivilegedPermission("registerRcsAvailabilityCallback");
James.cf Lincad981c2019-12-10 20:37:56 +0800185 final long token = Binder.clearCallingIdentity();
186 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800187 getRcsFeatureController(subId).registerRcsAvailabilityCallback(subId, callback);
188 } catch (ImsException e) {
James.cf Lincad981c2019-12-10 20:37:56 +0800189 Log.e(TAG, "registerRcsAvailabilityCallback: sudId=" + subId + ", " + e.getMessage());
190 throw new ServiceSpecificException(e.getCode());
191 } finally {
192 Binder.restoreCallingIdentity(token);
193 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800194 }
195
James.cf Lincad981c2019-12-10 20:37:56 +0800196 /**
197 * Remove the registered capability callback.
198 *
199 * @param subId the subscription ID
200 * @param callback The ImsCapabilityCallback to be removed.
201 */
James.cf Linaf3183c2019-10-24 00:59:00 +0800202 @Override
James.cf Lincad981c2019-12-10 20:37:56 +0800203 public void unregisterRcsAvailabilityCallback(int subId, IImsCapabilityCallback callback) {
James.cf Linaf3183c2019-10-24 00:59:00 +0800204 enforceReadPrivilegedPermission("unregisterRcsAvailabilityCallback");
James.cf Lincad981c2019-12-10 20:37:56 +0800205 final long token = Binder.clearCallingIdentity();
206 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800207 getRcsFeatureController(subId).unregisterRcsAvailabilityCallback(subId, callback);
James.cf Lincad981c2019-12-10 20:37:56 +0800208 } finally {
209 Binder.restoreCallingIdentity(token);
210 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800211 }
212
James.cf Lincad981c2019-12-10 20:37:56 +0800213 /**
214 * Query for the capability of an IMS RCS service
215 *
216 * @param subId the subscription ID
217 * @param capability the RCS capability to query.
218 * @param radioTech the radio tech that this capability failed for
219 * @return true if the RCS capability is capable for this subscription, false otherwise.
220 */
James.cf Linaf3183c2019-10-24 00:59:00 +0800221 @Override
222 public boolean isCapable(int subId,
James.cf Lincad981c2019-12-10 20:37:56 +0800223 @RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability,
224 @ImsRegistrationImplBase.ImsRegistrationTech int radioTech) {
James.cf Linaf3183c2019-10-24 00:59:00 +0800225 enforceReadPrivilegedPermission("isCapable");
James.cf Lincad981c2019-12-10 20:37:56 +0800226 final long token = Binder.clearCallingIdentity();
227 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800228 return getRcsFeatureController(subId).isCapable(capability, radioTech);
229 } catch (ImsException e) {
James.cf Lincad981c2019-12-10 20:37:56 +0800230 Log.e(TAG, "isCapable: sudId=" + subId
231 + ", capability=" + capability + ", " + e.getMessage());
232 return false;
233 } finally {
234 Binder.restoreCallingIdentity(token);
235 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800236 }
237
James.cf Lincad981c2019-12-10 20:37:56 +0800238 /**
239 * Query the availability of an IMS RCS capability.
240 *
241 * @param subId the subscription ID
242 * @param capability the RCS capability to query.
243 * @return true if the RCS capability is currently available for the associated subscription,
244 * false otherwise.
245 */
James.cf Linaf3183c2019-10-24 00:59:00 +0800246 @Override
247 public boolean isAvailable(int subId,
248 @RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability) {
249 enforceReadPrivilegedPermission("isAvailable");
James.cf Lincad981c2019-12-10 20:37:56 +0800250 final long token = Binder.clearCallingIdentity();
251 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800252 return getRcsFeatureController(subId).isAvailable(capability);
253 } catch (ImsException e) {
James.cf Lincad981c2019-12-10 20:37:56 +0800254 Log.e(TAG, "isAvailable: sudId=" + subId
255 + ", capability=" + capability + ", " + e.getMessage());
256 return false;
257 } finally {
258 Binder.restoreCallingIdentity(token);
259 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800260 }
261
262 @Override
Brad Ebinger8b79edc2020-02-27 19:13:24 -0800263 public void requestCapabilities(int subId, String callingPackage, String callingFeatureId,
264 List<Uri> contactNumbers, IRcsUceControllerCallback c) {
James.cf Linaf3183c2019-10-24 00:59:00 +0800265 enforceReadPrivilegedPermission("requestCapabilities");
Brad Ebingera68a4972020-01-30 17:31:23 -0800266 final long token = Binder.clearCallingIdentity();
267 try {
James.cf Lin99a360d2020-11-04 10:48:37 +0800268 UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
269 UceControllerManager.class);
270 if (uceCtrlManager == null) {
Brad Ebingera68a4972020-01-30 17:31:23 -0800271 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
272 "This subscription does not support UCE.");
273 }
James.cf Lin99a360d2020-11-04 10:48:37 +0800274 uceCtrlManager.requestCapabilities(contactNumbers, c);
275 } catch (ImsException e) {
276 throw new ServiceSpecificException(e.getCode(), e.getMessage());
Brad Ebingera68a4972020-01-30 17:31:23 -0800277 } finally {
278 Binder.restoreCallingIdentity(token);
Brad Ebinger1aa94992020-01-22 14:17:23 -0800279 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800280 }
281
282 @Override
James.cf Linbcdf8b32021-01-14 16:44:13 +0800283 public void requestAvailability(int subId, String callingPackage,
James.cf Lin64e91212020-10-30 01:09:52 +0800284 String callingFeatureId, Uri contactNumber, IRcsUceControllerCallback c) {
James.cf Linbcdf8b32021-01-14 16:44:13 +0800285 enforceReadPrivilegedPermission("requestAvailability");
Brad Ebingera68a4972020-01-30 17:31:23 -0800286 final long token = Binder.clearCallingIdentity();
287 try {
James.cf Lin99a360d2020-11-04 10:48:37 +0800288 UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
289 UceControllerManager.class);
290 if (uceCtrlManager == null) {
Brad Ebingera68a4972020-01-30 17:31:23 -0800291 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
292 "This subscription does not support UCE.");
293 }
James.cf Lin99a360d2020-11-04 10:48:37 +0800294 uceCtrlManager.requestNetworkAvailability(contactNumber, c);
295 } catch (ImsException e) {
296 throw new ServiceSpecificException(e.getCode(), e.getMessage());
297 } finally {
298 Binder.restoreCallingIdentity(token);
299 }
300 }
301
302 @Override
303 public @PublishState int getUcePublishState(int subId) {
304 enforceReadPrivilegedPermission("getUcePublishState");
305 final long token = Binder.clearCallingIdentity();
306 try {
307 UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
308 UceControllerManager.class);
309 if (uceCtrlManager == null) {
310 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
311 "This subscription does not support UCE.");
312 }
313 return uceCtrlManager.getUcePublishState();
314 } catch (ImsException e) {
315 throw new ServiceSpecificException(e.getCode(), e.getMessage());
316 } finally {
317 Binder.restoreCallingIdentity(token);
318 }
319 }
320
321 @Override
322 public void registerUcePublishStateCallback(int subId, IRcsUcePublishStateCallback c) {
323 enforceReadPrivilegedPermission("registerUcePublishStateCallback");
324 final long token = Binder.clearCallingIdentity();
325 try {
326 UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
327 UceControllerManager.class);
328 if (uceCtrlManager == null) {
329 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
330 "This subscription does not support UCE.");
331 }
332 uceCtrlManager.registerPublishStateCallback(c);
333 } catch (ImsException e) {
334 throw new ServiceSpecificException(e.getCode(), e.getMessage());
335 } finally {
336 Binder.restoreCallingIdentity(token);
337 }
338 }
339
340 @Override
341 public void unregisterUcePublishStateCallback(int subId, IRcsUcePublishStateCallback c) {
342 enforceReadPrivilegedPermission("unregisterUcePublishStateCallback");
343 final long token = Binder.clearCallingIdentity();
344 try {
345 UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
346 UceControllerManager.class);
347 if (uceCtrlManager == null) {
348 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
349 "This subscription does not support UCE.");
350 }
351 uceCtrlManager.unregisterPublishStateCallback(c);
Brad Ebingera68a4972020-01-30 17:31:23 -0800352 } finally {
353 Binder.restoreCallingIdentity(token);
Brad Ebinger1aa94992020-01-22 14:17:23 -0800354 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800355 }
356
357 @Override
Brad Ebinger8b79edc2020-02-27 19:13:24 -0800358 public boolean isUceSettingEnabled(int subId, String callingPackage, String callingFeatureId) {
359 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
360 mApp, subId, callingPackage, callingFeatureId, "isUceSettingEnabled")) {
361 Log.w(TAG, "isUceSettingEnabled: READ_PHONE_STATE app op disabled when accessing "
362 + "isUceSettingEnabled");
363 return false;
364 }
365 final long token = Binder.clearCallingIdentity();
366 try {
367 return SubscriptionManager.getBooleanSubscriptionProperty(subId,
368 SubscriptionManager.IMS_RCS_UCE_ENABLED, false /*defaultValue*/, mApp);
369 } finally {
370 Binder.restoreCallingIdentity(token);
371 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800372 }
373
374 @Override
375 public void setUceSettingEnabled(int subId, boolean isEnabled) {
376 enforceModifyPermission();
Brad Ebinger8b79edc2020-02-27 19:13:24 -0800377 final long token = Binder.clearCallingIdentity();
378 try {
379 SubscriptionManager.setSubscriptionProperty(subId,
380 SubscriptionManager.IMS_RCS_UCE_ENABLED, (isEnabled ? "1" : "0"));
381 } finally {
382 Binder.restoreCallingIdentity(token);
383 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800384 }
385
Brad Ebingerb989c7c2020-09-23 17:03:48 -0700386 @Override
387 public boolean isSipDelegateSupported(int subId) {
388 enforceReadPrivilegedPermission("isSipDelegateSupported");
389 final long token = Binder.clearCallingIdentity();
390 try {
391 SipTransportController transport = getRcsFeatureController(subId).getFeature(
392 SipTransportController.class);
393 if (transport == null) {
394 return false;
395 }
396 return transport.isSupported(subId);
397 } catch (ImsException e) {
398 throw new ServiceSpecificException(e.getCode(), e.getMessage());
399 } catch (ServiceSpecificException e) {
400 if (e.errorCode == ImsException.CODE_ERROR_UNSUPPORTED_OPERATION) {
401 return false;
402 }
403 throw e;
404 } finally {
405 Binder.restoreCallingIdentity(token);
406 }
407 }
408
Brad Ebingeraf1e9832020-10-14 10:49:28 -0700409 @Override
Brad Ebinger63b6f5a2020-10-27 11:43:35 -0700410 public void createSipDelegate(int subId, DelegateRequest request, String packageName,
Brad Ebingeraf1e9832020-10-14 10:49:28 -0700411 ISipDelegateConnectionStateCallback delegateState,
412 ISipDelegateMessageCallback delegateMessage) {
413 enforceModifyPermission();
Brad Ebinger63b6f5a2020-10-27 11:43:35 -0700414 if (!UserHandle.getUserHandleForUid(Binder.getCallingUid()).isSystem()) {
415 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
416 "SipDelegate creation is only available to primary user.");
417 }
418 try {
419 int remoteUid = mApp.getPackageManager().getPackageUid(packageName, 0 /*flags*/);
420 if (Binder.getCallingUid() != remoteUid) {
421 throw new SecurityException("passed in packageName does not match the caller");
422 }
423 } catch (PackageManager.NameNotFoundException e) {
424 throw new SecurityException("Passed in PackageName can not be found on device");
425 }
Brad Ebingeraf1e9832020-10-14 10:49:28 -0700426
427 final long identity = Binder.clearCallingIdentity();
428 SipTransportController transport = getRcsFeatureController(subId).getFeature(
429 SipTransportController.class);
430 if (transport == null) {
431 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
432 "This subscription does not support the creation of SIP delegates");
433 }
434 try {
Brad Ebinger63b6f5a2020-10-27 11:43:35 -0700435 transport.createSipDelegate(subId, request, packageName, delegateState,
436 delegateMessage);
Brad Ebingeraf1e9832020-10-14 10:49:28 -0700437 } catch (ImsException e) {
438 throw new ServiceSpecificException(e.getCode(), e.getMessage());
439 } finally {
440 Binder.restoreCallingIdentity(identity);
441 }
442 }
443
444 @Override
445 public void destroySipDelegate(int subId, ISipDelegate connection, int reason) {
446 enforceModifyPermission();
447
448 final long identity = Binder.clearCallingIdentity();
449 try {
Brad Ebinger63b6f5a2020-10-27 11:43:35 -0700450 SipTransportController transport = getRcsFeatureController(subId).getFeature(
451 SipTransportController.class);
452 if (transport == null) {
453 return;
454 }
455 transport.destroySipDelegate(subId, connection, reason);
Brad Ebingeraf1e9832020-10-14 10:49:28 -0700456 } finally {
457 Binder.restoreCallingIdentity(identity);
458 }
459 }
460
Brad Ebinger36221382020-12-09 00:33:39 +0000461 @Override
462 public void triggerNetworkRegistration(int subId, ISipDelegate connection, int sipCode,
463 String sipReason) {
464 enforceModifyPermission();
465
466 final long identity = Binder.clearCallingIdentity();
467 try {
468 SipTransportController transport = getRcsFeatureController(subId).getFeature(
469 SipTransportController.class);
470 if (transport == null) {
471 return;
472 }
473 transport.triggerFullNetworkRegistration(subId, connection, sipCode, sipReason);
474 } finally {
475 Binder.restoreCallingIdentity(identity);
476 }
477 }
478
James.cf Linaf3183c2019-10-24 00:59:00 +0800479 /**
Brad Ebingere3ae65a2020-09-11 12:45:11 -0700480 * Registers for updates to the RcsFeature connection through the IImsServiceFeatureCallback
481 * callback.
482 */
483 @Override
Brad Ebinger6366ce92020-10-01 13:51:05 -0700484 public void registerRcsFeatureCallback(int slotId, IImsServiceFeatureCallback callback) {
Brad Ebingere3ae65a2020-09-11 12:45:11 -0700485 enforceModifyPermission();
486
487 final long identity = Binder.clearCallingIdentity();
488 try {
489 if (mImsResolver == null) {
490 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
491 "Device does not support IMS");
492 }
Brad Ebinger6366ce92020-10-01 13:51:05 -0700493 mImsResolver.listenForFeature(slotId, ImsFeature.FEATURE_RCS, callback);
Brad Ebingere3ae65a2020-09-11 12:45:11 -0700494 } finally {
495 Binder.restoreCallingIdentity(identity);
496 }
497 }
Brad Ebinger6366ce92020-10-01 13:51:05 -0700498
Brad Ebingere3ae65a2020-09-11 12:45:11 -0700499 /**
500 * Unregister a previously registered IImsServiceFeatureCallback associated with an ImsFeature.
501 */
502 @Override
503 public void unregisterImsFeatureCallback(IImsServiceFeatureCallback callback) {
504 enforceModifyPermission();
505
506 final long identity = Binder.clearCallingIdentity();
507 try {
508 if (mImsResolver == null) return;
509 mImsResolver.unregisterImsFeatureCallback(callback);
510 } finally {
511 Binder.restoreCallingIdentity(identity);
512 }
513 }
514
515 /**
James.cf Linaf3183c2019-10-24 00:59:00 +0800516 * Make sure either called from same process as self (phone) or IPC caller has read privilege.
517 *
518 * @throws SecurityException if the caller does not have the required permission
519 */
520 private void enforceReadPrivilegedPermission(String message) {
521 mApp.enforceCallingOrSelfPermission(
522 android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, message);
523 }
524
525 /**
526 * Make sure the caller has the MODIFY_PHONE_STATE permission.
527 *
528 * @throws SecurityException if the caller does not have the required permission
529 */
530 private void enforceModifyPermission() {
531 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE, null);
532 }
James.cf Lincad981c2019-12-10 20:37:56 +0800533
534 /**
James.cf Lindc2d5422019-12-31 14:40:25 +0800535 * Retrieve ImsPhone instance.
James.cf Lincad981c2019-12-10 20:37:56 +0800536 *
537 * @param subId the subscription ID
James.cf Lindc2d5422019-12-31 14:40:25 +0800538 * @return The ImsPhone instance
539 * @throws ServiceSpecificException if getting ImsPhone instance failed.
James.cf Lincad981c2019-12-10 20:37:56 +0800540 */
James.cf Lindc2d5422019-12-31 14:40:25 +0800541 private ImsPhone getImsPhone(int subId) {
542 if (!ImsManager.isImsSupportedOnDevice(mApp)) {
543 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
544 "IMS is not available on device.");
545 }
James.cf Lincad981c2019-12-10 20:37:56 +0800546 Phone phone = PhoneGlobals.getPhone(subId);
547 if (phone == null) {
548 throw new ServiceSpecificException(ImsException.CODE_ERROR_INVALID_SUBSCRIPTION,
549 "Invalid subscription Id: " + subId);
550 }
551 ImsPhone imsPhone = (ImsPhone) phone.getImsPhone();
552 if (imsPhone == null) {
James.cf Lindc2d5422019-12-31 14:40:25 +0800553 throw new ServiceSpecificException(ImsException.CODE_ERROR_SERVICE_UNAVAILABLE,
554 "Cannot find ImsPhone instance: " + subId);
555 }
556 return imsPhone;
557 }
558
559 /**
560 * Retrieve RcsFeatureManager instance.
561 *
562 * @param subId the subscription ID
563 * @return The RcsFeatureManager instance
564 * @throws ServiceSpecificException if getting RcsFeatureManager instance failed.
565 */
Brad Ebingera68a4972020-01-30 17:31:23 -0800566 private RcsFeatureController getRcsFeatureController(int subId) {
James.cf Lindc2d5422019-12-31 14:40:25 +0800567 if (!ImsManager.isImsSupportedOnDevice(mApp)) {
James.cf Lincad981c2019-12-10 20:37:56 +0800568 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
James.cf Lindc2d5422019-12-31 14:40:25 +0800569 "IMS is not available on device.");
570 }
Brad Ebingera68a4972020-01-30 17:31:23 -0800571 if (mRcsService == null) {
572 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
573 "IMS is not available on device.");
574 }
James.cf Lindc2d5422019-12-31 14:40:25 +0800575 Phone phone = PhoneGlobals.getPhone(subId);
576 if (phone == null) {
577 throw new ServiceSpecificException(ImsException.CODE_ERROR_INVALID_SUBSCRIPTION,
578 "Invalid subscription Id: " + subId);
579 }
Brad Ebingera68a4972020-01-30 17:31:23 -0800580 int slotId = phone.getPhoneId();
581 RcsFeatureController c = mRcsService.getFeatureController(slotId);
582 if (c == null) {
Brad Ebinger036dc9e2020-02-06 15:49:06 -0800583 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
584 "The requested operation is not supported for subId " + subId);
James.cf Lincad981c2019-12-10 20:37:56 +0800585 }
Brad Ebingera68a4972020-01-30 17:31:23 -0800586 return c;
James.cf Lincad981c2019-12-10 20:37:56 +0800587 }
James.cf Linc9f35a42020-01-15 02:35:22 +0800588
589 void setRcsService(TelephonyRcsService rcsService) {
590 mRcsService = rcsService;
591 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800592}