blob: a778f6ae88e0a0fc16da029f38a4bdbcfd6fd2b9 [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
joonhunshin2c33ed92023-12-12 14:29:23 +000019import static android.content.pm.PackageManager.FEATURE_TELEPHONY_IMS;
20import static android.content.pm.PackageManager.FEATURE_TELEPHONY_IMS_SINGLE_REGISTRATION;
21import static android.telephony.TelephonyManager.ENABLE_FEATURE_MAPPING;
22
Brad Ebinger4df7e242021-02-17 23:23:21 +000023import android.Manifest;
joonhunshin2c33ed92023-12-12 14:29:23 +000024import android.annotation.NonNull;
25import android.annotation.Nullable;
Hyunho8ea90f32021-11-16 08:53:02 +000026import android.app.compat.CompatChanges;
27import android.compat.annotation.ChangeId;
28import android.compat.annotation.EnabledAfter;
Brad Ebinger63b6f5a2020-10-27 11:43:35 -070029import android.content.pm.PackageManager;
James.cf Linaf3183c2019-10-24 00:59:00 +080030import android.net.Uri;
James.cf Lincad981c2019-12-10 20:37:56 +080031import android.os.Binder;
Hyunho8ea90f32021-11-16 08:53:02 +000032import android.os.Build;
James.cf Lincad981c2019-12-10 20:37:56 +080033import android.os.RemoteException;
James.cf Lincad981c2019-12-10 20:37:56 +080034import android.os.ServiceSpecificException;
Brad Ebinger63b6f5a2020-10-27 11:43:35 -070035import android.os.UserHandle;
Brad Ebingerb7a866a2020-01-22 17:51:55 -080036import android.telephony.SubscriptionManager;
Peter Wangc035ce42020-01-08 21:00:22 -080037import android.telephony.TelephonyFrameworkInitializer;
Brad Ebingeraf1e9832020-10-14 10:49:28 -070038import android.telephony.ims.DelegateRequest;
James.cf Lincad981c2019-12-10 20:37:56 +080039import android.telephony.ims.ImsException;
Brad Ebingerd4c5bde2021-02-12 06:18:28 +000040import android.telephony.ims.RcsContactUceCapability;
James.cf Lin99a360d2020-11-04 10:48:37 +080041import android.telephony.ims.RcsUceAdapter.PublishState;
James.cf Lindc2d5422019-12-31 14:40:25 +080042import android.telephony.ims.RegistrationManager;
James.cf Linaf3183c2019-10-24 00:59:00 +080043import android.telephony.ims.aidl.IImsCapabilityCallback;
44import android.telephony.ims.aidl.IImsRcsController;
James.cf Lindc2d5422019-12-31 14:40:25 +080045import android.telephony.ims.aidl.IImsRegistrationCallback;
James.cf Linaf3183c2019-10-24 00:59:00 +080046import android.telephony.ims.aidl.IRcsUceControllerCallback;
James.cf Lincdad3862020-02-25 15:55:03 +080047import android.telephony.ims.aidl.IRcsUcePublishStateCallback;
Brad Ebingeraf1e9832020-10-14 10:49:28 -070048import android.telephony.ims.aidl.ISipDelegate;
49import android.telephony.ims.aidl.ISipDelegateConnectionStateCallback;
50import android.telephony.ims.aidl.ISipDelegateMessageCallback;
Brad Ebingere3ae65a2020-09-11 12:45:11 -070051import android.telephony.ims.feature.ImsFeature;
James.cf Linaf3183c2019-10-24 00:59:00 +080052import android.telephony.ims.feature.RcsFeature;
James.cf Lincad981c2019-12-10 20:37:56 +080053import android.telephony.ims.stub.ImsRegistrationImplBase;
James.cf Linaf3183c2019-10-24 00:59:00 +080054import android.util.Log;
55
James.cf Lindc2d5422019-12-31 14:40:25 +080056import com.android.ims.ImsManager;
Brad Ebingere3ae65a2020-09-11 12:45:11 -070057import com.android.ims.internal.IImsServiceFeatureCallback;
James.cf Lindc2d5422019-12-31 14:40:25 +080058import com.android.internal.telephony.IIntegerConsumer;
sungcheol ahn3991d2d2022-11-10 02:10:49 +000059import com.android.internal.telephony.ISipDialogStateCallback;
James.cf Lincad981c2019-12-10 20:37:56 +080060import com.android.internal.telephony.Phone;
Brad Ebinger8b79edc2020-02-27 19:13:24 -080061import com.android.internal.telephony.TelephonyPermissions;
joonhunshin2c33ed92023-12-12 14:29:23 +000062import com.android.internal.telephony.flags.FeatureFlags;
Brad Ebingere3ae65a2020-09-11 12:45:11 -070063import com.android.internal.telephony.ims.ImsResolver;
Brad Ebingera68a4972020-01-30 17:31:23 -080064import com.android.services.telephony.rcs.RcsFeatureController;
Brad Ebingerb989c7c2020-09-23 17:03:48 -070065import com.android.services.telephony.rcs.SipTransportController;
James.cf Linc9f35a42020-01-15 02:35:22 +080066import com.android.services.telephony.rcs.TelephonyRcsService;
James.cf Lin99a360d2020-11-04 10:48:37 +080067import com.android.services.telephony.rcs.UceControllerManager;
James.cf Lincad981c2019-12-10 20:37:56 +080068
James.cf Linaf3183c2019-10-24 00:59:00 +080069import java.util.List;
Brad Ebingerd4c5bde2021-02-12 06:18:28 +000070import java.util.Set;
James.cf Linaf3183c2019-10-24 00:59:00 +080071
72/**
73 * Implementation of the IImsRcsController interface.
74 */
75public class ImsRcsController extends IImsRcsController.Stub {
76 private static final String TAG = "ImsRcsController";
77
78 /** The singleton instance. */
79 private static ImsRcsController sInstance;
80
81 private PhoneGlobals mApp;
James.cf Linc9f35a42020-01-15 02:35:22 +080082 private TelephonyRcsService mRcsService;
Brad Ebingere3ae65a2020-09-11 12:45:11 -070083 private ImsResolver mImsResolver;
joonhunshin2c33ed92023-12-12 14:29:23 +000084 private FeatureFlags mFeatureFlags;
85 private PackageManager mPackageManager;
Brad Ebinger49a72b42021-01-29 00:55:24 +000086 // set by shell cmd phone src set-device-enabled true/false
87 private Boolean mSingleRegistrationOverride;
James.cf Linaf3183c2019-10-24 00:59:00 +080088
89 /**
Hyunho8ea90f32021-11-16 08:53:02 +000090 * For apps targeting Android T and above, support the publishing state on APIs, such as
91 * {@code RcsUceAdapter#PUBLISH_STATE_PUBLISHING}
92 * @hide
93 */
94 @ChangeId
95 @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.S)
96 public static final long SUPPORT_PUBLISHING_STATE = 202894742;
97
98 /**
James.cf Linaf3183c2019-10-24 00:59:00 +080099 * Initialize the singleton ImsRcsController instance.
100 * This is only done once, at startup, from PhoneApp.onCreate().
101 */
joonhunshin2c33ed92023-12-12 14:29:23 +0000102 static ImsRcsController init(PhoneGlobals app, FeatureFlags featureFlags) {
James.cf Linaf3183c2019-10-24 00:59:00 +0800103 synchronized (ImsRcsController.class) {
104 if (sInstance == null) {
joonhunshin2c33ed92023-12-12 14:29:23 +0000105 sInstance = new ImsRcsController(app, featureFlags);
James.cf Linaf3183c2019-10-24 00:59:00 +0800106 } else {
107 Log.wtf(TAG, "init() called multiple times! sInstance = " + sInstance);
108 }
109 return sInstance;
110 }
111 }
112
113 /** Private constructor; @see init() */
joonhunshin2c33ed92023-12-12 14:29:23 +0000114 private ImsRcsController(PhoneGlobals app, FeatureFlags featureFlags) {
James.cf Linaf3183c2019-10-24 00:59:00 +0800115 Log.i(TAG, "ImsRcsController");
116 mApp = app;
joonhunshin2c33ed92023-12-12 14:29:23 +0000117 mFeatureFlags = featureFlags;
118 mPackageManager = mApp.getPackageManager();
Peter Wangc035ce42020-01-08 21:00:22 -0800119 TelephonyFrameworkInitializer
120 .getTelephonyServiceManager().getTelephonyImsServiceRegisterer().register(this);
Brad Ebingerd1947d82021-05-17 20:54:49 +0000121 mImsResolver = ImsResolver.getInstance();
James.cf Linaf3183c2019-10-24 00:59:00 +0800122 }
123
James.cf Lincad981c2019-12-10 20:37:56 +0800124 /**
Brad Ebingera68a4972020-01-30 17:31:23 -0800125 * Register a {@link RegistrationManager.RegistrationCallback} to receive IMS network
126 * registration state.
James.cf Lindc2d5422019-12-31 14:40:25 +0800127 */
128 @Override
Brad Ebingera68a4972020-01-30 17:31:23 -0800129 public void registerImsRegistrationCallback(int subId, IImsRegistrationCallback callback) {
Nathan Harold75a9ff12021-04-06 11:26:02 -0700130 TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
James.cf Linf020d162021-01-31 22:15:52 +0800131 mApp, subId, "registerImsRegistrationCallback");
joonhunshin2c33ed92023-12-12 14:29:23 +0000132
133 enforceTelephonyFeatureWithException(getCurrentPackageName(),
134 FEATURE_TELEPHONY_IMS, "registerImsRegistrationCallback");
135
James.cf Lindc2d5422019-12-31 14:40:25 +0800136 final long token = Binder.clearCallingIdentity();
137 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800138 getRcsFeatureController(subId).registerImsRegistrationCallback(subId, callback);
139 } catch (ImsException e) {
James.cf Lindc2d5422019-12-31 14:40:25 +0800140 Log.e(TAG, "registerImsRegistrationCallback: sudId=" + subId + ", " + e.getMessage());
141 throw new ServiceSpecificException(e.getCode());
142 } finally {
143 Binder.restoreCallingIdentity(token);
144 }
145 }
146
147 /**
Brad Ebingera68a4972020-01-30 17:31:23 -0800148 * Removes an existing {@link RegistrationManager.RegistrationCallback}.
James.cf Lindc2d5422019-12-31 14:40:25 +0800149 */
150 @Override
151 public void unregisterImsRegistrationCallback(int subId, IImsRegistrationCallback callback) {
Nathan Harold75a9ff12021-04-06 11:26:02 -0700152 TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
James.cf Linf020d162021-01-31 22:15:52 +0800153 mApp, subId, "unregisterImsRegistrationCallback");
joonhunshin2c33ed92023-12-12 14:29:23 +0000154
155 enforceTelephonyFeatureWithException(getCurrentPackageName(),
156 FEATURE_TELEPHONY_IMS, "unregisterImsRegistrationCallback");
157
James.cf Lindc2d5422019-12-31 14:40:25 +0800158 final long token = Binder.clearCallingIdentity();
159 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800160 getRcsFeatureController(subId).unregisterImsRegistrationCallback(subId, callback);
James.cf Lindc2d5422019-12-31 14:40:25 +0800161 } catch (ServiceSpecificException e) {
162 Log.e(TAG, "unregisterImsRegistrationCallback: error=" + e.errorCode);
163 } finally {
164 Binder.restoreCallingIdentity(token);
165 }
166 }
167
168 /**
169 * Get the IMS service registration state for the RcsFeature associated with this sub id.
170 */
171 @Override
172 public void getImsRcsRegistrationState(int subId, IIntegerConsumer consumer) {
Nathan Harold75a9ff12021-04-06 11:26:02 -0700173 TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
James.cf Linf020d162021-01-31 22:15:52 +0800174 mApp, subId, "getImsRcsRegistrationState");
joonhunshin2c33ed92023-12-12 14:29:23 +0000175
176 enforceTelephonyFeatureWithException(getCurrentPackageName(),
177 FEATURE_TELEPHONY_IMS, "getImsRcsRegistrationState");
178
James.cf Lindc2d5422019-12-31 14:40:25 +0800179 final long token = Binder.clearCallingIdentity();
180 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800181 getRcsFeatureController(subId).getRegistrationState(regState -> {
James.cf Lindc2d5422019-12-31 14:40:25 +0800182 try {
183 consumer.accept((regState == null)
184 ? RegistrationManager.REGISTRATION_STATE_NOT_REGISTERED : regState);
185 } catch (RemoteException e) {
186 Log.w(TAG, "getImsRcsRegistrationState: callback is not available.");
187 }
188 });
189 } finally {
190 Binder.restoreCallingIdentity(token);
191 }
192 }
193
194 /**
195 * Gets the Transport Type associated with the current IMS RCS registration.
196 */
197 @Override
198 public void getImsRcsRegistrationTransportType(int subId, IIntegerConsumer consumer) {
Nathan Harold75a9ff12021-04-06 11:26:02 -0700199 TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
James.cf Linf020d162021-01-31 22:15:52 +0800200 mApp, subId, "getImsRcsRegistrationTransportType");
joonhunshin2c33ed92023-12-12 14:29:23 +0000201
202 enforceTelephonyFeatureWithException(getCurrentPackageName(),
203 FEATURE_TELEPHONY_IMS, "getImsRcsRegistrationTransportType");
204
James.cf Lindc2d5422019-12-31 14:40:25 +0800205 final long token = Binder.clearCallingIdentity();
206 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800207 getRcsFeatureController(subId).getRegistrationTech(regTech -> {
James.cf Lindc2d5422019-12-31 14:40:25 +0800208 // Convert registration tech from ImsRegistrationImplBase -> RegistrationManager
209 int regTechConverted = (regTech == null)
210 ? ImsRegistrationImplBase.REGISTRATION_TECH_NONE : regTech;
211 regTechConverted = RegistrationManager.IMS_REG_TO_ACCESS_TYPE_MAP.get(
212 regTechConverted);
213 try {
214 consumer.accept(regTechConverted);
215 } catch (RemoteException e) {
216 Log.w(TAG, "getImsRcsRegistrationTransportType: callback is not available.");
217 }
218 });
219 } finally {
220 Binder.restoreCallingIdentity(token);
221 }
222 }
223
224 /**
James.cf Lincad981c2019-12-10 20:37:56 +0800225 * Register a capability callback which will provide RCS availability updates for the
226 * subscription specified.
227 *
228 * @param subId the subscription ID
229 * @param callback The ImsCapabilityCallback to be registered.
230 */
James.cf Linaf3183c2019-10-24 00:59:00 +0800231 @Override
Brad Ebingera68a4972020-01-30 17:31:23 -0800232 public void registerRcsAvailabilityCallback(int subId, IImsCapabilityCallback callback) {
James.cf Linaf3183c2019-10-24 00:59:00 +0800233 enforceReadPrivilegedPermission("registerRcsAvailabilityCallback");
joonhunshin2c33ed92023-12-12 14:29:23 +0000234
235 enforceTelephonyFeatureWithException(getCurrentPackageName(),
236 FEATURE_TELEPHONY_IMS, "registerRcsAvailabilityCallback");
237
James.cf Lincad981c2019-12-10 20:37:56 +0800238 final long token = Binder.clearCallingIdentity();
239 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800240 getRcsFeatureController(subId).registerRcsAvailabilityCallback(subId, callback);
241 } catch (ImsException e) {
James.cf Lincad981c2019-12-10 20:37:56 +0800242 Log.e(TAG, "registerRcsAvailabilityCallback: sudId=" + subId + ", " + e.getMessage());
243 throw new ServiceSpecificException(e.getCode());
244 } finally {
245 Binder.restoreCallingIdentity(token);
246 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800247 }
248
James.cf Lincad981c2019-12-10 20:37:56 +0800249 /**
250 * Remove the registered capability callback.
251 *
252 * @param subId the subscription ID
253 * @param callback The ImsCapabilityCallback to be removed.
254 */
James.cf Linaf3183c2019-10-24 00:59:00 +0800255 @Override
James.cf Lincad981c2019-12-10 20:37:56 +0800256 public void unregisterRcsAvailabilityCallback(int subId, IImsCapabilityCallback callback) {
James.cf Linaf3183c2019-10-24 00:59:00 +0800257 enforceReadPrivilegedPermission("unregisterRcsAvailabilityCallback");
joonhunshin2c33ed92023-12-12 14:29:23 +0000258
259 enforceTelephonyFeatureWithException(getCurrentPackageName(),
260 FEATURE_TELEPHONY_IMS, "unregisterRcsAvailabilityCallback");
261
James.cf Lincad981c2019-12-10 20:37:56 +0800262 final long token = Binder.clearCallingIdentity();
263 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800264 getRcsFeatureController(subId).unregisterRcsAvailabilityCallback(subId, callback);
Brad Ebinger919631e2021-06-02 17:46:35 -0700265 } catch (ServiceSpecificException e) {
266 Log.e(TAG, "unregisterRcsAvailabilityCallback: error=" + e.errorCode);
James.cf Lincad981c2019-12-10 20:37:56 +0800267 } finally {
268 Binder.restoreCallingIdentity(token);
269 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800270 }
271
James.cf Lincad981c2019-12-10 20:37:56 +0800272 /**
273 * Query for the capability of an IMS RCS service
274 *
275 * @param subId the subscription ID
276 * @param capability the RCS capability to query.
James.cf Linf020d162021-01-31 22:15:52 +0800277 * @param radioTech the radio technology type that we are querying.
James.cf Lincad981c2019-12-10 20:37:56 +0800278 * @return true if the RCS capability is capable for this subscription, false otherwise.
279 */
James.cf Linaf3183c2019-10-24 00:59:00 +0800280 @Override
281 public boolean isCapable(int subId,
James.cf Lincad981c2019-12-10 20:37:56 +0800282 @RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability,
283 @ImsRegistrationImplBase.ImsRegistrationTech int radioTech) {
James.cf Linaf3183c2019-10-24 00:59:00 +0800284 enforceReadPrivilegedPermission("isCapable");
joonhunshin2c33ed92023-12-12 14:29:23 +0000285
286 enforceTelephonyFeatureWithException(getCurrentPackageName(),
287 FEATURE_TELEPHONY_IMS, "isCapable");
288
James.cf Lincad981c2019-12-10 20:37:56 +0800289 final long token = Binder.clearCallingIdentity();
290 try {
Brad Ebingera68a4972020-01-30 17:31:23 -0800291 return getRcsFeatureController(subId).isCapable(capability, radioTech);
292 } catch (ImsException e) {
James.cf Lincad981c2019-12-10 20:37:56 +0800293 Log.e(TAG, "isCapable: sudId=" + subId
294 + ", capability=" + capability + ", " + e.getMessage());
Brad Ebingere3885b22022-02-16 13:18:59 -0800295 throw new ServiceSpecificException(e.getCode(), e.getMessage());
James.cf Lincad981c2019-12-10 20:37:56 +0800296 } finally {
297 Binder.restoreCallingIdentity(token);
298 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800299 }
300
James.cf Lincad981c2019-12-10 20:37:56 +0800301 /**
302 * Query the availability of an IMS RCS capability.
303 *
304 * @param subId the subscription ID
305 * @param capability the RCS capability to query.
306 * @return true if the RCS capability is currently available for the associated subscription,
James.cf Linf020d162021-01-31 22:15:52 +0800307 * @param radioTech the radio technology type that we are querying.
James.cf Lincad981c2019-12-10 20:37:56 +0800308 * false otherwise.
309 */
James.cf Linaf3183c2019-10-24 00:59:00 +0800310 @Override
311 public boolean isAvailable(int subId,
James.cf Linf020d162021-01-31 22:15:52 +0800312 @RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability,
313 @ImsRegistrationImplBase.ImsRegistrationTech int radioTech) {
James.cf Linaf3183c2019-10-24 00:59:00 +0800314 enforceReadPrivilegedPermission("isAvailable");
joonhunshin2c33ed92023-12-12 14:29:23 +0000315
316 enforceTelephonyFeatureWithException(getCurrentPackageName(),
317 FEATURE_TELEPHONY_IMS, "isAvailable");
318
James.cf Lincad981c2019-12-10 20:37:56 +0800319 final long token = Binder.clearCallingIdentity();
320 try {
James.cf Linf020d162021-01-31 22:15:52 +0800321 return getRcsFeatureController(subId).isAvailable(capability, radioTech);
Brad Ebingera68a4972020-01-30 17:31:23 -0800322 } catch (ImsException e) {
James.cf Lincad981c2019-12-10 20:37:56 +0800323 Log.e(TAG, "isAvailable: sudId=" + subId
324 + ", capability=" + capability + ", " + e.getMessage());
Brad Ebingere3885b22022-02-16 13:18:59 -0800325 throw new ServiceSpecificException(e.getCode(), e.getMessage());
James.cf Lincad981c2019-12-10 20:37:56 +0800326 } finally {
327 Binder.restoreCallingIdentity(token);
328 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800329 }
330
331 @Override
Brad Ebinger8b79edc2020-02-27 19:13:24 -0800332 public void requestCapabilities(int subId, String callingPackage, String callingFeatureId,
333 List<Uri> contactNumbers, IRcsUceControllerCallback c) {
James.cf Lin051dd252021-01-21 03:30:54 +0800334 enforceAccessUserCapabilityExchangePermission("requestCapabilities");
335 enforceReadContactsPermission("requestCapabilities");
joonhunshin2c33ed92023-12-12 14:29:23 +0000336
337 enforceTelephonyFeatureWithException(callingPackage,
338 FEATURE_TELEPHONY_IMS, "requestCapabilities");
339
Brad Ebingera68a4972020-01-30 17:31:23 -0800340 final long token = Binder.clearCallingIdentity();
341 try {
James.cf Lin99a360d2020-11-04 10:48:37 +0800342 UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
343 UceControllerManager.class);
344 if (uceCtrlManager == null) {
Brad Ebingera68a4972020-01-30 17:31:23 -0800345 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
346 "This subscription does not support UCE.");
347 }
James.cf Lin99a360d2020-11-04 10:48:37 +0800348 uceCtrlManager.requestCapabilities(contactNumbers, c);
349 } catch (ImsException e) {
350 throw new ServiceSpecificException(e.getCode(), e.getMessage());
Brad Ebingera68a4972020-01-30 17:31:23 -0800351 } finally {
352 Binder.restoreCallingIdentity(token);
Brad Ebinger1aa94992020-01-22 14:17:23 -0800353 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800354 }
355
356 @Override
James.cf Linbcdf8b32021-01-14 16:44:13 +0800357 public void requestAvailability(int subId, String callingPackage,
James.cf Lin64e91212020-10-30 01:09:52 +0800358 String callingFeatureId, Uri contactNumber, IRcsUceControllerCallback c) {
James.cf Lin051dd252021-01-21 03:30:54 +0800359 enforceAccessUserCapabilityExchangePermission("requestAvailability");
360 enforceReadContactsPermission("requestAvailability");
joonhunshin2c33ed92023-12-12 14:29:23 +0000361
362 enforceTelephonyFeatureWithException(callingPackage,
363 FEATURE_TELEPHONY_IMS, "requestAvailability");
364
Brad Ebingera68a4972020-01-30 17:31:23 -0800365 final long token = Binder.clearCallingIdentity();
366 try {
James.cf Lin99a360d2020-11-04 10:48:37 +0800367 UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
368 UceControllerManager.class);
369 if (uceCtrlManager == null) {
Brad Ebingera68a4972020-01-30 17:31:23 -0800370 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
371 "This subscription does not support UCE.");
372 }
James.cf Lin99a360d2020-11-04 10:48:37 +0800373 uceCtrlManager.requestNetworkAvailability(contactNumber, c);
374 } catch (ImsException e) {
375 throw new ServiceSpecificException(e.getCode(), e.getMessage());
376 } finally {
377 Binder.restoreCallingIdentity(token);
378 }
379 }
380
381 @Override
382 public @PublishState int getUcePublishState(int subId) {
383 enforceReadPrivilegedPermission("getUcePublishState");
joonhunshin2c33ed92023-12-12 14:29:23 +0000384
385 enforceTelephonyFeatureWithException(getCurrentPackageName(),
386 FEATURE_TELEPHONY_IMS, "getUcePublishState");
387
Hyunho8ea90f32021-11-16 08:53:02 +0000388 final int uid = Binder.getCallingUid();
James.cf Lin99a360d2020-11-04 10:48:37 +0800389 final long token = Binder.clearCallingIdentity();
Hyunho8ea90f32021-11-16 08:53:02 +0000390 boolean isSupportPublishingState = false;
James.cf Lin99a360d2020-11-04 10:48:37 +0800391 try {
392 UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
393 UceControllerManager.class);
394 if (uceCtrlManager == null) {
395 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
396 "This subscription does not support UCE.");
397 }
Hyunho8ea90f32021-11-16 08:53:02 +0000398 if (CompatChanges.isChangeEnabled(SUPPORT_PUBLISHING_STATE, uid)) {
399 isSupportPublishingState = true;
400 }
401 return uceCtrlManager.getUcePublishState(isSupportPublishingState);
James.cf Lin99a360d2020-11-04 10:48:37 +0800402 } catch (ImsException e) {
403 throw new ServiceSpecificException(e.getCode(), e.getMessage());
404 } finally {
405 Binder.restoreCallingIdentity(token);
406 }
407 }
408
Brad Ebingerd4c5bde2021-02-12 06:18:28 +0000409 /**
410 * Add new feature tags to the Set used to calculate the capabilities in PUBLISH.
411 */
412 // Used for SHELL command only right now.
413 public RcsContactUceCapability addUceRegistrationOverrideShell(int subId,
414 Set<String> featureTags) throws ImsException {
415 // Permission check happening in PhoneInterfaceManager.
Brad Ebinger919631e2021-06-02 17:46:35 -0700416 try {
417 UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
418 UceControllerManager.class);
419 if (uceCtrlManager == null) {
420 return null;
421 }
422 return uceCtrlManager.addUceRegistrationOverride(featureTags);
423 } catch (ServiceSpecificException e) {
424 throw new ImsException(e.getMessage(), e.errorCode);
Brad Ebingerd4c5bde2021-02-12 06:18:28 +0000425 }
Brad Ebingerd4c5bde2021-02-12 06:18:28 +0000426 }
427
428 /**
429 * Remove existing feature tags to the Set used to calculate the capabilities in PUBLISH.
430 */
431 // Used for SHELL command only right now.
432 public RcsContactUceCapability removeUceRegistrationOverrideShell(int subId,
433 Set<String> featureTags) throws ImsException {
434 // Permission check happening in PhoneInterfaceManager.
Brad Ebinger919631e2021-06-02 17:46:35 -0700435 try {
436 UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
437 UceControllerManager.class);
438 if (uceCtrlManager == null) {
439 return null;
440 }
441 return uceCtrlManager.removeUceRegistrationOverride(featureTags);
442 } catch (ServiceSpecificException e) {
443 throw new ImsException(e.getMessage(), e.errorCode);
Brad Ebingerd4c5bde2021-02-12 06:18:28 +0000444 }
Brad Ebingerd4c5bde2021-02-12 06:18:28 +0000445 }
446
447 /**
448 * Clear all overrides in the Set used to calculate the capabilities in PUBLISH.
449 */
450 // Used for SHELL command only right now.
451 public RcsContactUceCapability clearUceRegistrationOverrideShell(int subId)
452 throws ImsException {
Brad Ebinger919631e2021-06-02 17:46:35 -0700453 try {
454 // Permission check happening in PhoneInterfaceManager.
455 UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
456 UceControllerManager.class);
457 if (uceCtrlManager == null) {
458 return null;
459 }
460 return uceCtrlManager.clearUceRegistrationOverride();
461 } catch (ServiceSpecificException e) {
462 throw new ImsException(e.getMessage(), e.errorCode);
Brad Ebingerd4c5bde2021-02-12 06:18:28 +0000463 }
Brad Ebingerd4c5bde2021-02-12 06:18:28 +0000464 }
465
466 /**
467 * @return current RcsContactUceCapability instance that will be used for PUBLISH.
468 */
469 // Used for SHELL command only right now.
470 public RcsContactUceCapability getLatestRcsContactUceCapabilityShell(int subId)
471 throws ImsException {
Brad Ebinger919631e2021-06-02 17:46:35 -0700472 try {
473 // Permission check happening in PhoneInterfaceManager.
474 UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
475 UceControllerManager.class);
476 if (uceCtrlManager == null) {
477 return null;
478 }
479 return uceCtrlManager.getLatestRcsContactUceCapability();
480 } catch (ServiceSpecificException e) {
481 throw new ImsException(e.getMessage(), e.errorCode);
Brad Ebingerd4c5bde2021-02-12 06:18:28 +0000482 }
Brad Ebingerd4c5bde2021-02-12 06:18:28 +0000483 }
484
485 /**
486 * @return the PIDf XML used in the last PUBLISH procedure or "none" if the device is not
487 * published. Returns {@code null} if the operation failed due to an error.
488 */
489 // Used for SHELL command only right now.
490 public String getLastUcePidfXmlShell(int subId) throws ImsException {
Brad Ebinger919631e2021-06-02 17:46:35 -0700491 try {
492 // Permission check happening in PhoneInterfaceManager.
493 UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
494 UceControllerManager.class);
495 if (uceCtrlManager == null) {
496 return null;
497 }
498 String pidfXml = uceCtrlManager.getLastPidfXml();
499 return pidfXml == null ? "none" : pidfXml;
500 } catch (ServiceSpecificException e) {
501 throw new ImsException(e.getMessage(), e.errorCode);
Brad Ebingerd4c5bde2021-02-12 06:18:28 +0000502 }
Brad Ebingerd4c5bde2021-02-12 06:18:28 +0000503 }
504
James.cf Line8713a42021-04-29 16:04:26 +0800505 /**
506 * Remove UCE requests cannot be sent to the network status.
507 * @return true if this command is successful.
508 */
509 // Used for SHELL command only right now.
510 public boolean removeUceRequestDisallowedStatus(int subId) throws ImsException {
Brad Ebinger919631e2021-06-02 17:46:35 -0700511 try {
James.cf Linc6b449f2021-06-05 01:11:15 +0800512 UceControllerManager uceCtrlManager = getRcsFeatureController(subId, true).getFeature(
Brad Ebinger919631e2021-06-02 17:46:35 -0700513 UceControllerManager.class);
514 if (uceCtrlManager == null) {
515 return false;
516 }
517 return uceCtrlManager.removeUceRequestDisallowedStatus();
518 } catch (ServiceSpecificException e) {
519 throw new ImsException(e.getMessage(), e.errorCode);
James.cf Line8713a42021-04-29 16:04:26 +0800520 }
James.cf Line8713a42021-04-29 16:04:26 +0800521 }
522
James.cf Lin0fc71b02021-05-25 01:37:38 +0800523 /**
524 * Set the timeout for contact capabilities request.
525 */
526 // Used for SHELL command only right now.
527 public boolean setCapabilitiesRequestTimeout(int subId, long timeoutAfter) throws ImsException {
Brad Ebinger919631e2021-06-02 17:46:35 -0700528 try {
James.cf Linc6b449f2021-06-05 01:11:15 +0800529 UceControllerManager uceCtrlManager = getRcsFeatureController(subId, true).getFeature(
Brad Ebinger919631e2021-06-02 17:46:35 -0700530 UceControllerManager.class);
531 if (uceCtrlManager == null) {
532 return false;
533 }
534 return uceCtrlManager.setCapabilitiesRequestTimeout(timeoutAfter);
535 } catch (ServiceSpecificException e) {
536 throw new ImsException(e.getMessage(), e.errorCode);
James.cf Lin0fc71b02021-05-25 01:37:38 +0800537 }
James.cf Lin0fc71b02021-05-25 01:37:38 +0800538 }
539
James.cf Lin99a360d2020-11-04 10:48:37 +0800540 @Override
541 public void registerUcePublishStateCallback(int subId, IRcsUcePublishStateCallback c) {
542 enforceReadPrivilegedPermission("registerUcePublishStateCallback");
joonhunshin2c33ed92023-12-12 14:29:23 +0000543
544 enforceTelephonyFeatureWithException(getCurrentPackageName(),
545 FEATURE_TELEPHONY_IMS, "registerUcePublishStateCallback");
546
Hyunho8ea90f32021-11-16 08:53:02 +0000547 final int uid = Binder.getCallingUid();
James.cf Lin99a360d2020-11-04 10:48:37 +0800548 final long token = Binder.clearCallingIdentity();
Hyunho8ea90f32021-11-16 08:53:02 +0000549 boolean isSupportPublishingState = false;
James.cf Lin99a360d2020-11-04 10:48:37 +0800550 try {
551 UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
552 UceControllerManager.class);
553 if (uceCtrlManager == null) {
554 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
555 "This subscription does not support UCE.");
556 }
Hyunho8ea90f32021-11-16 08:53:02 +0000557
558 if (CompatChanges.isChangeEnabled(SUPPORT_PUBLISHING_STATE, uid)) {
559 isSupportPublishingState = true;
560 }
561 uceCtrlManager.registerPublishStateCallback(c, isSupportPublishingState);
James.cf Lin99a360d2020-11-04 10:48:37 +0800562 } catch (ImsException e) {
563 throw new ServiceSpecificException(e.getCode(), e.getMessage());
564 } finally {
565 Binder.restoreCallingIdentity(token);
566 }
567 }
568
569 @Override
570 public void unregisterUcePublishStateCallback(int subId, IRcsUcePublishStateCallback c) {
571 enforceReadPrivilegedPermission("unregisterUcePublishStateCallback");
joonhunshin2c33ed92023-12-12 14:29:23 +0000572
573 enforceTelephonyFeatureWithException(getCurrentPackageName(),
574 FEATURE_TELEPHONY_IMS, "unregisterUcePublishStateCallback");
575
James.cf Lin99a360d2020-11-04 10:48:37 +0800576 final long token = Binder.clearCallingIdentity();
577 try {
578 UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
579 UceControllerManager.class);
580 if (uceCtrlManager == null) {
581 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
582 "This subscription does not support UCE.");
583 }
584 uceCtrlManager.unregisterPublishStateCallback(c);
Brad Ebinger919631e2021-06-02 17:46:35 -0700585 } catch (ServiceSpecificException e) {
586 Log.e(TAG, "unregisterUcePublishStateCallback: error=" + e.errorCode);
Brad Ebingera68a4972020-01-30 17:31:23 -0800587 } finally {
588 Binder.restoreCallingIdentity(token);
Brad Ebinger1aa94992020-01-22 14:17:23 -0800589 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800590 }
591
592 @Override
Brad Ebinger8b79edc2020-02-27 19:13:24 -0800593 public boolean isUceSettingEnabled(int subId, String callingPackage, String callingFeatureId) {
594 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
595 mApp, subId, callingPackage, callingFeatureId, "isUceSettingEnabled")) {
596 Log.w(TAG, "isUceSettingEnabled: READ_PHONE_STATE app op disabled when accessing "
597 + "isUceSettingEnabled");
598 return false;
599 }
joonhunshin2c33ed92023-12-12 14:29:23 +0000600
601 enforceTelephonyFeatureWithException(callingPackage,
602 FEATURE_TELEPHONY_IMS, "isUceSettingEnabled");
603
Brad Ebinger8b79edc2020-02-27 19:13:24 -0800604 final long token = Binder.clearCallingIdentity();
605 try {
606 return SubscriptionManager.getBooleanSubscriptionProperty(subId,
607 SubscriptionManager.IMS_RCS_UCE_ENABLED, false /*defaultValue*/, mApp);
608 } finally {
609 Binder.restoreCallingIdentity(token);
610 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800611 }
612
613 @Override
614 public void setUceSettingEnabled(int subId, boolean isEnabled) {
615 enforceModifyPermission();
joonhunshin2c33ed92023-12-12 14:29:23 +0000616
617 enforceTelephonyFeatureWithException(getCurrentPackageName(),
618 FEATURE_TELEPHONY_IMS, "setUceSettingEnabled");
619
Brad Ebinger8b79edc2020-02-27 19:13:24 -0800620 final long token = Binder.clearCallingIdentity();
621 try {
622 SubscriptionManager.setSubscriptionProperty(subId,
623 SubscriptionManager.IMS_RCS_UCE_ENABLED, (isEnabled ? "1" : "0"));
624 } finally {
625 Binder.restoreCallingIdentity(token);
626 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800627 }
628
Brad Ebingerb989c7c2020-09-23 17:03:48 -0700629 @Override
630 public boolean isSipDelegateSupported(int subId) {
Brad Ebinger4df7e242021-02-17 23:23:21 +0000631 TelephonyPermissions.enforceAnyPermissionGranted(mApp, Binder.getCallingUid(),
632 "isSipDelegateSupported",
633 Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION,
634 Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
Brad Ebinger49a72b42021-01-29 00:55:24 +0000635 if (!isImsSingleRegistrationSupportedOnDevice()) {
636 return false;
637 }
Brad Ebingerb989c7c2020-09-23 17:03:48 -0700638 final long token = Binder.clearCallingIdentity();
639 try {
640 SipTransportController transport = getRcsFeatureController(subId).getFeature(
641 SipTransportController.class);
642 if (transport == null) {
643 return false;
644 }
645 return transport.isSupported(subId);
646 } catch (ImsException e) {
647 throw new ServiceSpecificException(e.getCode(), e.getMessage());
648 } catch (ServiceSpecificException e) {
649 if (e.errorCode == ImsException.CODE_ERROR_UNSUPPORTED_OPERATION) {
650 return false;
651 }
652 throw e;
653 } finally {
654 Binder.restoreCallingIdentity(token);
655 }
656 }
657
Brad Ebingeraf1e9832020-10-14 10:49:28 -0700658 @Override
Brad Ebinger63b6f5a2020-10-27 11:43:35 -0700659 public void createSipDelegate(int subId, DelegateRequest request, String packageName,
Brad Ebingeraf1e9832020-10-14 10:49:28 -0700660 ISipDelegateConnectionStateCallback delegateState,
661 ISipDelegateMessageCallback delegateMessage) {
Brad Ebinger4df7e242021-02-17 23:23:21 +0000662 enforceImsSingleRegistrationPermission("createSipDelegate");
Brad Ebinger49a72b42021-01-29 00:55:24 +0000663 if (!isImsSingleRegistrationSupportedOnDevice()) {
664 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
665 "SipDelegate creation is only supported for devices supporting IMS single "
666 + "registration");
667 }
Brad Ebinger63b6f5a2020-10-27 11:43:35 -0700668 if (!UserHandle.getUserHandleForUid(Binder.getCallingUid()).isSystem()) {
669 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
670 "SipDelegate creation is only available to primary user.");
671 }
672 try {
673 int remoteUid = mApp.getPackageManager().getPackageUid(packageName, 0 /*flags*/);
674 if (Binder.getCallingUid() != remoteUid) {
675 throw new SecurityException("passed in packageName does not match the caller");
676 }
677 } catch (PackageManager.NameNotFoundException e) {
678 throw new SecurityException("Passed in PackageName can not be found on device");
679 }
Brad Ebingeraf1e9832020-10-14 10:49:28 -0700680
Jinyoung Jeongca77e1c2021-10-21 04:34:46 +0000681 final int uid = Binder.getCallingUid();
Brad Ebingeraf1e9832020-10-14 10:49:28 -0700682 final long identity = Binder.clearCallingIdentity();
683 SipTransportController transport = getRcsFeatureController(subId).getFeature(
684 SipTransportController.class);
685 if (transport == null) {
686 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
687 "This subscription does not support the creation of SIP delegates");
688 }
689 try {
Jinyoung Jeongca77e1c2021-10-21 04:34:46 +0000690 transport.createSipDelegate(subId, uid, request, packageName, delegateState,
Brad Ebinger63b6f5a2020-10-27 11:43:35 -0700691 delegateMessage);
Brad Ebingeraf1e9832020-10-14 10:49:28 -0700692 } catch (ImsException e) {
693 throw new ServiceSpecificException(e.getCode(), e.getMessage());
694 } finally {
695 Binder.restoreCallingIdentity(identity);
696 }
697 }
698
699 @Override
700 public void destroySipDelegate(int subId, ISipDelegate connection, int reason) {
Brad Ebinger652411e2021-06-30 09:30:35 -0700701 // Do not check permissions here - the caller needs to have a connection already from the
702 // create method to call this method.
703 if (connection == null) {
704 return;
705 }
Brad Ebingeraf1e9832020-10-14 10:49:28 -0700706 final long identity = Binder.clearCallingIdentity();
707 try {
Brad Ebinger63b6f5a2020-10-27 11:43:35 -0700708 SipTransportController transport = getRcsFeatureController(subId).getFeature(
709 SipTransportController.class);
710 if (transport == null) {
711 return;
712 }
713 transport.destroySipDelegate(subId, connection, reason);
Brad Ebinger919631e2021-06-02 17:46:35 -0700714 } catch (ServiceSpecificException e) {
715 Log.e(TAG, "destroySipDelegate: error=" + e.errorCode);
Brad Ebingeraf1e9832020-10-14 10:49:28 -0700716 } finally {
717 Binder.restoreCallingIdentity(identity);
718 }
719 }
720
Brad Ebinger36221382020-12-09 00:33:39 +0000721 @Override
722 public void triggerNetworkRegistration(int subId, ISipDelegate connection, int sipCode,
723 String sipReason) {
Brad Ebinger4df7e242021-02-17 23:23:21 +0000724 enforceImsSingleRegistrationPermission("triggerNetworkRegistration");
Brad Ebinger36221382020-12-09 00:33:39 +0000725
726 final long identity = Binder.clearCallingIdentity();
727 try {
728 SipTransportController transport = getRcsFeatureController(subId).getFeature(
729 SipTransportController.class);
730 if (transport == null) {
731 return;
732 }
733 transport.triggerFullNetworkRegistration(subId, connection, sipCode, sipReason);
Brad Ebinger919631e2021-06-02 17:46:35 -0700734 } catch (ServiceSpecificException e) {
735 Log.e(TAG, "triggerNetworkRegistration: error=" + e.errorCode);
Brad Ebinger36221382020-12-09 00:33:39 +0000736 } finally {
737 Binder.restoreCallingIdentity(identity);
738 }
739 }
740
James.cf Linaf3183c2019-10-24 00:59:00 +0800741 /**
sungcheol ahn3991d2d2022-11-10 02:10:49 +0000742 * Register a state of Sip Dialog callback
743 */
744 @Override
745 public void registerSipDialogStateCallback(int subId, ISipDialogStateCallback cb) {
746 enforceReadPrivilegedPermission("registerSipDialogStateCallback");
747 if (cb == null) {
748 throw new IllegalArgumentException("SipDialogStateCallback is null");
749 }
750 final long identity = Binder.clearCallingIdentity();
751 if (!SubscriptionManager.isValidSubscriptionId(subId)) {
752 throw new IllegalArgumentException("Invalid Subscription ID: " + subId);
753 }
joonhunshin2c33ed92023-12-12 14:29:23 +0000754
755 enforceTelephonyFeatureWithException(getCurrentPackageName(),
756 FEATURE_TELEPHONY_IMS_SINGLE_REGISTRATION, "registerSipDialogStateCallback");
757
sungcheol ahn3991d2d2022-11-10 02:10:49 +0000758 try {
759 SipTransportController transport = getRcsFeatureController(subId).getFeature(
760 SipTransportController.class);
761 if (transport == null) {
762 throw new ServiceSpecificException(ImsException.CODE_ERROR_SERVICE_UNAVAILABLE,
763 "This transport does not support the registerSipDialogStateCallback"
764 + " of SIP delegates");
765 }
766 transport.addCallbackForSipDialogState(subId, cb);
767 } finally {
768 Binder.restoreCallingIdentity(identity);
769 }
770 }
771
772 /**
773 * Unregister a state of Sip Dialog callback
774 */
775 @Override
776 public void unregisterSipDialogStateCallback(int subId, ISipDialogStateCallback cb) {
777 enforceReadPrivilegedPermission("unregisterSipDialogStateCallback");
778 if (cb == null) {
779 throw new IllegalArgumentException("SipDialogStateCallback is null");
780 }
781 final long identity = Binder.clearCallingIdentity();
782 if (!SubscriptionManager.isValidSubscriptionId(subId)) {
783 throw new IllegalArgumentException("Invalid Subscription ID: " + subId);
784 }
joonhunshin2c33ed92023-12-12 14:29:23 +0000785
786 enforceTelephonyFeatureWithException(getCurrentPackageName(),
787 FEATURE_TELEPHONY_IMS_SINGLE_REGISTRATION, "unregisterSipDialogStateCallback");
788
sungcheol ahn3991d2d2022-11-10 02:10:49 +0000789 try {
790 SipTransportController transport = getRcsFeatureController(subId).getFeature(
791 SipTransportController.class);
792 if (transport == null) {
793 throw new ServiceSpecificException(ImsException.CODE_ERROR_SERVICE_UNAVAILABLE,
794 "This transport does not support the unregisterSipDialogStateCallback"
795 + " of SIP delegates");
796 }
797 transport.removeCallbackForSipDialogState(subId, cb);
798 } finally {
799 Binder.restoreCallingIdentity(identity);
800 }
801 }
802
803 /**
Brad Ebingere3ae65a2020-09-11 12:45:11 -0700804 * Registers for updates to the RcsFeature connection through the IImsServiceFeatureCallback
805 * callback.
806 */
807 @Override
Brad Ebinger6366ce92020-10-01 13:51:05 -0700808 public void registerRcsFeatureCallback(int slotId, IImsServiceFeatureCallback callback) {
Brad Ebingere3ae65a2020-09-11 12:45:11 -0700809 enforceModifyPermission();
810
811 final long identity = Binder.clearCallingIdentity();
812 try {
813 if (mImsResolver == null) {
814 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
815 "Device does not support IMS");
816 }
Brad Ebinger6366ce92020-10-01 13:51:05 -0700817 mImsResolver.listenForFeature(slotId, ImsFeature.FEATURE_RCS, callback);
Brad Ebingere3ae65a2020-09-11 12:45:11 -0700818 } finally {
819 Binder.restoreCallingIdentity(identity);
820 }
821 }
Brad Ebinger6366ce92020-10-01 13:51:05 -0700822
Brad Ebingere3ae65a2020-09-11 12:45:11 -0700823 /**
824 * Unregister a previously registered IImsServiceFeatureCallback associated with an ImsFeature.
825 */
826 @Override
827 public void unregisterImsFeatureCallback(IImsServiceFeatureCallback callback) {
828 enforceModifyPermission();
829
830 final long identity = Binder.clearCallingIdentity();
831 try {
832 if (mImsResolver == null) return;
833 mImsResolver.unregisterImsFeatureCallback(callback);
834 } finally {
835 Binder.restoreCallingIdentity(identity);
836 }
837 }
838
839 /**
James.cf Linaf3183c2019-10-24 00:59:00 +0800840 * Make sure either called from same process as self (phone) or IPC caller has read privilege.
841 *
842 * @throws SecurityException if the caller does not have the required permission
843 */
844 private void enforceReadPrivilegedPermission(String message) {
845 mApp.enforceCallingOrSelfPermission(
846 android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, message);
847 }
848
849 /**
Brad Ebinger4df7e242021-02-17 23:23:21 +0000850 * @throws SecurityException if the caller does not have the required
851 * PERFORM_IMS_SINGLE_REGISTRATION permission.
852 */
853 private void enforceImsSingleRegistrationPermission(String message) {
854 mApp.enforceCallingOrSelfPermission(
855 Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION, message);
856 }
857
858 /**
James.cf Linaf3183c2019-10-24 00:59:00 +0800859 * Make sure the caller has the MODIFY_PHONE_STATE permission.
860 *
861 * @throws SecurityException if the caller does not have the required permission
862 */
863 private void enforceModifyPermission() {
864 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE, null);
865 }
James.cf Lincad981c2019-12-10 20:37:56 +0800866
867 /**
James.cf Lin051dd252021-01-21 03:30:54 +0800868 * Make sure the caller has the ACCESS_RCS_USER_CAPABILITY_EXCHANGE permission.
869 *
870 * @throws SecurityException if the caller does not have the required permission.
871 */
872 private void enforceAccessUserCapabilityExchangePermission(String message) {
873 mApp.enforceCallingOrSelfPermission(
874 android.Manifest.permission.ACCESS_RCS_USER_CAPABILITY_EXCHANGE, message);
875 }
876
877 /**
878 * Make sure the caller has the READ_CONTACTS permission.
879 *
880 * @throws SecurityException if the caller does not have the required permission.
881 */
882 private void enforceReadContactsPermission(String message) {
883 mApp.enforceCallingOrSelfPermission(
884 android.Manifest.permission.READ_CONTACTS, message);
885 }
886
887 /**
James.cf Lindc2d5422019-12-31 14:40:25 +0800888 * Retrieve RcsFeatureManager instance.
889 *
890 * @param subId the subscription ID
891 * @return The RcsFeatureManager instance
892 * @throws ServiceSpecificException if getting RcsFeatureManager instance failed.
893 */
Brad Ebingera68a4972020-01-30 17:31:23 -0800894 private RcsFeatureController getRcsFeatureController(int subId) {
James.cf Linc6b449f2021-06-05 01:11:15 +0800895 return getRcsFeatureController(subId, false /* skipVerifyingConfig */);
896 }
897
898 /**
899 * Retrieve RcsFeatureManager instance.
900 *
901 * @param subId the subscription ID
902 * @param skipVerifyingConfig If the RCS configuration can be skip.
903 * @return The RcsFeatureManager instance
904 * @throws ServiceSpecificException if getting RcsFeatureManager instance failed.
905 */
906 private RcsFeatureController getRcsFeatureController(int subId, boolean skipVerifyingConfig) {
James.cf Lindc2d5422019-12-31 14:40:25 +0800907 if (!ImsManager.isImsSupportedOnDevice(mApp)) {
James.cf Lincad981c2019-12-10 20:37:56 +0800908 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
James.cf Lindc2d5422019-12-31 14:40:25 +0800909 "IMS is not available on device.");
910 }
Brad Ebingera68a4972020-01-30 17:31:23 -0800911 if (mRcsService == null) {
912 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
913 "IMS is not available on device.");
914 }
James.cf Lindc2d5422019-12-31 14:40:25 +0800915 Phone phone = PhoneGlobals.getPhone(subId);
916 if (phone == null) {
917 throw new ServiceSpecificException(ImsException.CODE_ERROR_INVALID_SUBSCRIPTION,
918 "Invalid subscription Id: " + subId);
919 }
Brad Ebingera68a4972020-01-30 17:31:23 -0800920 int slotId = phone.getPhoneId();
James.cf Linc6b449f2021-06-05 01:11:15 +0800921 if (!skipVerifyingConfig) {
922 verifyImsRcsConfiguredOrThrow(slotId);
Brad Ebingere3885b22022-02-16 13:18:59 -0800923 verifyRcsSubIdActiveOrThrow(slotId, subId);
James.cf Linc6b449f2021-06-05 01:11:15 +0800924 }
Brad Ebingera68a4972020-01-30 17:31:23 -0800925 RcsFeatureController c = mRcsService.getFeatureController(slotId);
926 if (c == null) {
Brad Ebingere3885b22022-02-16 13:18:59 -0800927 // If we hit this case, we have verified that TelephonyRcsService has processed any
928 // subId changes for the associated slot and applied configs. In this case, the configs
929 // do not have the RCS feature enabled.
Brad Ebinger036dc9e2020-02-06 15:49:06 -0800930 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
931 "The requested operation is not supported for subId " + subId);
James.cf Lincad981c2019-12-10 20:37:56 +0800932 }
Brad Ebingere3885b22022-02-16 13:18:59 -0800933 if (!skipVerifyingConfig && c.getAssociatedSubId() != subId) {
934 // If we hit this case, the ImsFeature has not finished setting up the RCS feature yet
935 // or the RCS feature has crashed and is being set up again.
936 Log.w(TAG, "getRcsFeatureController: service unavailable on slot " + slotId
937 + " for subId " + subId);
938 throw new ServiceSpecificException(ImsException.CODE_ERROR_SERVICE_UNAVAILABLE,
939 "The ImsService is not currently available for subid " + subId
940 + ", please try again");
941 }
Brad Ebingera68a4972020-01-30 17:31:23 -0800942 return c;
James.cf Lincad981c2019-12-10 20:37:56 +0800943 }
James.cf Linc9f35a42020-01-15 02:35:22 +0800944
Brad Ebinger919631e2021-06-02 17:46:35 -0700945 /**
Brad Ebingere3885b22022-02-16 13:18:59 -0800946 * Ensure the TelephonyRcsService is tracking the supplied subId for the supplied slotId and has
947 * set up the stack.
948 */
949 private void verifyRcsSubIdActiveOrThrow(int slotId, int subId) {
950 if (mRcsService.verifyActiveSubId(slotId, subId)) return;
951
952 Log.w(TAG, "verifyRcsSubIdActiveOrThrow: verify failed, service not set up yet on "
953 + "slot " + slotId + " for subId " + subId);
954 throw new ServiceSpecificException(ImsException.CODE_ERROR_SERVICE_UNAVAILABLE,
955 "ImsService set up in progress for subId " + subId
956 + ", please try again");
957 }
958
959 /**
Brad Ebinger919631e2021-06-02 17:46:35 -0700960 * Throw an ImsException if the IMS resolver does not have an ImsService configured for RCS
961 * for the given slot ID or no ImsResolver instance has been created.
962 * @param slotId The slot ID that the IMS service is created for.
963 * @throws ServiceSpecificException If there is no ImsService configured for this slot.
964 */
965 private void verifyImsRcsConfiguredOrThrow(int slotId) {
966 if (mImsResolver == null
967 || !mImsResolver.isImsServiceConfiguredForFeature(slotId, ImsFeature.FEATURE_RCS)) {
968 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
969 "This subscription does not support RCS");
970 }
971 }
972
Brad Ebinger49a72b42021-01-29 00:55:24 +0000973 private boolean isImsSingleRegistrationSupportedOnDevice() {
974 return mSingleRegistrationOverride != null ? mSingleRegistrationOverride
975 : mApp.getPackageManager().hasSystemFeature(
976 PackageManager.FEATURE_TELEPHONY_IMS_SINGLE_REGISTRATION);
977 }
978
joonhunshin2c33ed92023-12-12 14:29:23 +0000979 /**
980 * Get the current calling package name.
981 * @return the current calling package name
982 */
983 @Nullable
984 private String getCurrentPackageName() {
985 if (mPackageManager == null) return null;
986 String[] callingUids = mPackageManager.getPackagesForUid(Binder.getCallingUid());
987 return (callingUids == null) ? null : callingUids[0];
988 }
989
990 /**
991 * Make sure the device has required telephony feature
992 *
993 * @throws UnsupportedOperationException if the device does not have required telephony feature
994 */
995 private void enforceTelephonyFeatureWithException(@Nullable String callingPackage,
996 @NonNull String telephonyFeature, @NonNull String methodName) {
997 if (callingPackage == null || mPackageManager == null) {
998 return;
999 }
1000
1001 if (!mFeatureFlags.enforceTelephonyFeatureMappingForPublicApis()
1002 || !CompatChanges.isChangeEnabled(ENABLE_FEATURE_MAPPING, callingPackage,
1003 Binder.getCallingUserHandle())) {
1004 return;
1005 }
1006
1007 if (!mPackageManager.hasSystemFeature(telephonyFeature)) {
1008 throw new UnsupportedOperationException(
1009 methodName + " is unsupported without " + telephonyFeature);
1010 }
1011 }
1012
James.cf Linc9f35a42020-01-15 02:35:22 +08001013 void setRcsService(TelephonyRcsService rcsService) {
1014 mRcsService = rcsService;
1015 }
Brad Ebinger49a72b42021-01-29 00:55:24 +00001016
1017 /**
1018 * Override device RCS single registration support check for CTS testing or remove override
1019 * if the Boolean is set to null.
1020 */
1021 void setDeviceSingleRegistrationSupportOverride(Boolean deviceOverrideValue) {
1022 mSingleRegistrationOverride = deviceOverrideValue;
1023 }
James.cf Linaf3183c2019-10-24 00:59:00 +08001024}