blob: 52069b8e698ff01e9af0e2b0262a47e92ac805fa [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 Ebinger8b79edc2020-02-27 19:13:24 -0800266 if (!isUceSettingEnabled(subId, callingPackage, callingFeatureId)) {
267 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
268 "The user has not enabled UCE for this subscription.");
269 }
Brad Ebingera68a4972020-01-30 17:31:23 -0800270 final long token = Binder.clearCallingIdentity();
271 try {
James.cf Lin99a360d2020-11-04 10:48:37 +0800272 UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
273 UceControllerManager.class);
274 if (uceCtrlManager == null) {
Brad Ebingera68a4972020-01-30 17:31:23 -0800275 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
276 "This subscription does not support UCE.");
277 }
James.cf Lin99a360d2020-11-04 10:48:37 +0800278 uceCtrlManager.requestCapabilities(contactNumbers, c);
279 } catch (ImsException e) {
280 throw new ServiceSpecificException(e.getCode(), e.getMessage());
Brad Ebingera68a4972020-01-30 17:31:23 -0800281 } finally {
282 Binder.restoreCallingIdentity(token);
Brad Ebinger1aa94992020-01-22 14:17:23 -0800283 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800284 }
285
286 @Override
James.cf Lin64e91212020-10-30 01:09:52 +0800287 public void requestNetworkAvailability(int subId, String callingPackage,
288 String callingFeatureId, Uri contactNumber, IRcsUceControllerCallback c) {
289 enforceReadPrivilegedPermission("requestNetworkAvailability");
290 if (!isUceSettingEnabled(subId, callingPackage, callingFeatureId)) {
291 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
292 "The user has not enabled UCE for this subscription.");
293 }
Brad Ebingera68a4972020-01-30 17:31:23 -0800294 final long token = Binder.clearCallingIdentity();
295 try {
James.cf Lin99a360d2020-11-04 10:48:37 +0800296 UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
297 UceControllerManager.class);
298 if (uceCtrlManager == null) {
Brad Ebingera68a4972020-01-30 17:31:23 -0800299 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
300 "This subscription does not support UCE.");
301 }
James.cf Lin99a360d2020-11-04 10:48:37 +0800302 uceCtrlManager.requestNetworkAvailability(contactNumber, c);
303 } catch (ImsException e) {
304 throw new ServiceSpecificException(e.getCode(), e.getMessage());
305 } finally {
306 Binder.restoreCallingIdentity(token);
307 }
308 }
309
310 @Override
311 public @PublishState int getUcePublishState(int subId) {
312 enforceReadPrivilegedPermission("getUcePublishState");
313 final long token = Binder.clearCallingIdentity();
314 try {
315 UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
316 UceControllerManager.class);
317 if (uceCtrlManager == null) {
318 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
319 "This subscription does not support UCE.");
320 }
321 return uceCtrlManager.getUcePublishState();
322 } catch (ImsException e) {
323 throw new ServiceSpecificException(e.getCode(), e.getMessage());
324 } finally {
325 Binder.restoreCallingIdentity(token);
326 }
327 }
328
329 @Override
330 public void registerUcePublishStateCallback(int subId, IRcsUcePublishStateCallback c) {
331 enforceReadPrivilegedPermission("registerUcePublishStateCallback");
332 final long token = Binder.clearCallingIdentity();
333 try {
334 UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
335 UceControllerManager.class);
336 if (uceCtrlManager == null) {
337 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
338 "This subscription does not support UCE.");
339 }
340 uceCtrlManager.registerPublishStateCallback(c);
341 } catch (ImsException e) {
342 throw new ServiceSpecificException(e.getCode(), e.getMessage());
343 } finally {
344 Binder.restoreCallingIdentity(token);
345 }
346 }
347
348 @Override
349 public void unregisterUcePublishStateCallback(int subId, IRcsUcePublishStateCallback c) {
350 enforceReadPrivilegedPermission("unregisterUcePublishStateCallback");
351 final long token = Binder.clearCallingIdentity();
352 try {
353 UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
354 UceControllerManager.class);
355 if (uceCtrlManager == null) {
356 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
357 "This subscription does not support UCE.");
358 }
359 uceCtrlManager.unregisterPublishStateCallback(c);
Brad Ebingera68a4972020-01-30 17:31:23 -0800360 } finally {
361 Binder.restoreCallingIdentity(token);
Brad Ebinger1aa94992020-01-22 14:17:23 -0800362 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800363 }
364
365 @Override
Brad Ebinger8b79edc2020-02-27 19:13:24 -0800366 public boolean isUceSettingEnabled(int subId, String callingPackage, String callingFeatureId) {
367 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
368 mApp, subId, callingPackage, callingFeatureId, "isUceSettingEnabled")) {
369 Log.w(TAG, "isUceSettingEnabled: READ_PHONE_STATE app op disabled when accessing "
370 + "isUceSettingEnabled");
371 return false;
372 }
373 final long token = Binder.clearCallingIdentity();
374 try {
375 return SubscriptionManager.getBooleanSubscriptionProperty(subId,
376 SubscriptionManager.IMS_RCS_UCE_ENABLED, false /*defaultValue*/, mApp);
377 } finally {
378 Binder.restoreCallingIdentity(token);
379 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800380 }
381
382 @Override
383 public void setUceSettingEnabled(int subId, boolean isEnabled) {
384 enforceModifyPermission();
Brad Ebinger8b79edc2020-02-27 19:13:24 -0800385 final long token = Binder.clearCallingIdentity();
386 try {
387 SubscriptionManager.setSubscriptionProperty(subId,
388 SubscriptionManager.IMS_RCS_UCE_ENABLED, (isEnabled ? "1" : "0"));
389 } finally {
390 Binder.restoreCallingIdentity(token);
391 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800392 }
393
Brad Ebingerb989c7c2020-09-23 17:03:48 -0700394 @Override
395 public boolean isSipDelegateSupported(int subId) {
396 enforceReadPrivilegedPermission("isSipDelegateSupported");
397 final long token = Binder.clearCallingIdentity();
398 try {
399 SipTransportController transport = getRcsFeatureController(subId).getFeature(
400 SipTransportController.class);
401 if (transport == null) {
402 return false;
403 }
404 return transport.isSupported(subId);
405 } catch (ImsException e) {
406 throw new ServiceSpecificException(e.getCode(), e.getMessage());
407 } catch (ServiceSpecificException e) {
408 if (e.errorCode == ImsException.CODE_ERROR_UNSUPPORTED_OPERATION) {
409 return false;
410 }
411 throw e;
412 } finally {
413 Binder.restoreCallingIdentity(token);
414 }
415 }
416
Brad Ebingeraf1e9832020-10-14 10:49:28 -0700417 @Override
Brad Ebinger63b6f5a2020-10-27 11:43:35 -0700418 public void createSipDelegate(int subId, DelegateRequest request, String packageName,
Brad Ebingeraf1e9832020-10-14 10:49:28 -0700419 ISipDelegateConnectionStateCallback delegateState,
420 ISipDelegateMessageCallback delegateMessage) {
421 enforceModifyPermission();
Brad Ebinger63b6f5a2020-10-27 11:43:35 -0700422 if (!UserHandle.getUserHandleForUid(Binder.getCallingUid()).isSystem()) {
423 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
424 "SipDelegate creation is only available to primary user.");
425 }
426 try {
427 int remoteUid = mApp.getPackageManager().getPackageUid(packageName, 0 /*flags*/);
428 if (Binder.getCallingUid() != remoteUid) {
429 throw new SecurityException("passed in packageName does not match the caller");
430 }
431 } catch (PackageManager.NameNotFoundException e) {
432 throw new SecurityException("Passed in PackageName can not be found on device");
433 }
Brad Ebingeraf1e9832020-10-14 10:49:28 -0700434
435 final long identity = Binder.clearCallingIdentity();
436 SipTransportController transport = getRcsFeatureController(subId).getFeature(
437 SipTransportController.class);
438 if (transport == null) {
439 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
440 "This subscription does not support the creation of SIP delegates");
441 }
442 try {
Brad Ebinger63b6f5a2020-10-27 11:43:35 -0700443 transport.createSipDelegate(subId, request, packageName, delegateState,
444 delegateMessage);
Brad Ebingeraf1e9832020-10-14 10:49:28 -0700445 } catch (ImsException e) {
446 throw new ServiceSpecificException(e.getCode(), e.getMessage());
447 } finally {
448 Binder.restoreCallingIdentity(identity);
449 }
450 }
451
452 @Override
453 public void destroySipDelegate(int subId, ISipDelegate connection, int reason) {
454 enforceModifyPermission();
455
456 final long identity = Binder.clearCallingIdentity();
457 try {
Brad Ebinger63b6f5a2020-10-27 11:43:35 -0700458 SipTransportController transport = getRcsFeatureController(subId).getFeature(
459 SipTransportController.class);
460 if (transport == null) {
461 return;
462 }
463 transport.destroySipDelegate(subId, connection, reason);
Brad Ebingeraf1e9832020-10-14 10:49:28 -0700464 } finally {
465 Binder.restoreCallingIdentity(identity);
466 }
467 }
468
James.cf Linaf3183c2019-10-24 00:59:00 +0800469 /**
Brad Ebingere3ae65a2020-09-11 12:45:11 -0700470 * Registers for updates to the RcsFeature connection through the IImsServiceFeatureCallback
471 * callback.
472 */
473 @Override
Brad Ebinger6366ce92020-10-01 13:51:05 -0700474 public void registerRcsFeatureCallback(int slotId, IImsServiceFeatureCallback callback) {
Brad Ebingere3ae65a2020-09-11 12:45:11 -0700475 enforceModifyPermission();
476
477 final long identity = Binder.clearCallingIdentity();
478 try {
479 if (mImsResolver == null) {
480 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
481 "Device does not support IMS");
482 }
Brad Ebinger6366ce92020-10-01 13:51:05 -0700483 mImsResolver.listenForFeature(slotId, ImsFeature.FEATURE_RCS, callback);
Brad Ebingere3ae65a2020-09-11 12:45:11 -0700484 } finally {
485 Binder.restoreCallingIdentity(identity);
486 }
487 }
Brad Ebinger6366ce92020-10-01 13:51:05 -0700488
Brad Ebingere3ae65a2020-09-11 12:45:11 -0700489 /**
490 * Unregister a previously registered IImsServiceFeatureCallback associated with an ImsFeature.
491 */
492 @Override
493 public void unregisterImsFeatureCallback(IImsServiceFeatureCallback callback) {
494 enforceModifyPermission();
495
496 final long identity = Binder.clearCallingIdentity();
497 try {
498 if (mImsResolver == null) return;
499 mImsResolver.unregisterImsFeatureCallback(callback);
500 } finally {
501 Binder.restoreCallingIdentity(identity);
502 }
503 }
504
505 /**
James.cf Linaf3183c2019-10-24 00:59:00 +0800506 * Make sure either called from same process as self (phone) or IPC caller has read privilege.
507 *
508 * @throws SecurityException if the caller does not have the required permission
509 */
510 private void enforceReadPrivilegedPermission(String message) {
511 mApp.enforceCallingOrSelfPermission(
512 android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, message);
513 }
514
515 /**
516 * Make sure the caller has the MODIFY_PHONE_STATE permission.
517 *
518 * @throws SecurityException if the caller does not have the required permission
519 */
520 private void enforceModifyPermission() {
521 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE, null);
522 }
James.cf Lincad981c2019-12-10 20:37:56 +0800523
524 /**
James.cf Lindc2d5422019-12-31 14:40:25 +0800525 * Retrieve ImsPhone instance.
James.cf Lincad981c2019-12-10 20:37:56 +0800526 *
527 * @param subId the subscription ID
James.cf Lindc2d5422019-12-31 14:40:25 +0800528 * @return The ImsPhone instance
529 * @throws ServiceSpecificException if getting ImsPhone instance failed.
James.cf Lincad981c2019-12-10 20:37:56 +0800530 */
James.cf Lindc2d5422019-12-31 14:40:25 +0800531 private ImsPhone getImsPhone(int subId) {
532 if (!ImsManager.isImsSupportedOnDevice(mApp)) {
533 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
534 "IMS is not available on device.");
535 }
James.cf Lincad981c2019-12-10 20:37:56 +0800536 Phone phone = PhoneGlobals.getPhone(subId);
537 if (phone == null) {
538 throw new ServiceSpecificException(ImsException.CODE_ERROR_INVALID_SUBSCRIPTION,
539 "Invalid subscription Id: " + subId);
540 }
541 ImsPhone imsPhone = (ImsPhone) phone.getImsPhone();
542 if (imsPhone == null) {
James.cf Lindc2d5422019-12-31 14:40:25 +0800543 throw new ServiceSpecificException(ImsException.CODE_ERROR_SERVICE_UNAVAILABLE,
544 "Cannot find ImsPhone instance: " + subId);
545 }
546 return imsPhone;
547 }
548
549 /**
550 * Retrieve RcsFeatureManager instance.
551 *
552 * @param subId the subscription ID
553 * @return The RcsFeatureManager instance
554 * @throws ServiceSpecificException if getting RcsFeatureManager instance failed.
555 */
Brad Ebingera68a4972020-01-30 17:31:23 -0800556 private RcsFeatureController getRcsFeatureController(int subId) {
James.cf Lindc2d5422019-12-31 14:40:25 +0800557 if (!ImsManager.isImsSupportedOnDevice(mApp)) {
James.cf Lincad981c2019-12-10 20:37:56 +0800558 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
James.cf Lindc2d5422019-12-31 14:40:25 +0800559 "IMS is not available on device.");
560 }
Brad Ebingera68a4972020-01-30 17:31:23 -0800561 if (mRcsService == null) {
562 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
563 "IMS is not available on device.");
564 }
James.cf Lindc2d5422019-12-31 14:40:25 +0800565 Phone phone = PhoneGlobals.getPhone(subId);
566 if (phone == null) {
567 throw new ServiceSpecificException(ImsException.CODE_ERROR_INVALID_SUBSCRIPTION,
568 "Invalid subscription Id: " + subId);
569 }
Brad Ebingera68a4972020-01-30 17:31:23 -0800570 int slotId = phone.getPhoneId();
571 RcsFeatureController c = mRcsService.getFeatureController(slotId);
572 if (c == null) {
Brad Ebinger036dc9e2020-02-06 15:49:06 -0800573 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
574 "The requested operation is not supported for subId " + subId);
James.cf Lincad981c2019-12-10 20:37:56 +0800575 }
Brad Ebingera68a4972020-01-30 17:31:23 -0800576 return c;
James.cf Lincad981c2019-12-10 20:37:56 +0800577 }
James.cf Linc9f35a42020-01-15 02:35:22 +0800578
579 void setRcsService(TelephonyRcsService rcsService) {
580 mRcsService = rcsService;
581 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800582}