blob: 58ddf21888fc9cacee1b60a764a3036b1a079f8d [file] [log] [blame]
Brad Ebingerc5992532018-09-24 13:13:55 -07001/*
2 * Copyright (C) 2018 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 android.telephony.ims;
18
19
20import android.Manifest;
21import android.annotation.CallbackExecutor;
22import android.annotation.IntDef;
23import android.annotation.NonNull;
Brad Ebingeraec46b12019-02-28 13:10:32 -080024import android.annotation.Nullable;
Brad Ebingerc5992532018-09-24 13:13:55 -070025import android.annotation.RequiresPermission;
26import android.annotation.SystemApi;
27import android.content.Context;
28import android.net.Uri;
29import android.os.Binder;
30import android.os.RemoteException;
31import android.os.ServiceManager;
Brad Ebingerfd880802018-11-08 17:41:54 -080032import android.telephony.AccessNetworkConstants;
Brad Ebingerc5992532018-09-24 13:13:55 -070033import android.telephony.SubscriptionManager;
34import android.telephony.ims.aidl.IImsCapabilityCallback;
35import android.telephony.ims.aidl.IImsRegistrationCallback;
36import android.telephony.ims.feature.ImsFeature;
37import android.telephony.ims.feature.MmTelFeature;
38import android.telephony.ims.stub.ImsRegistrationImplBase;
Brad Ebingerfd880802018-11-08 17:41:54 -080039import android.util.Log;
Brad Ebingerc5992532018-09-24 13:13:55 -070040
Brad Ebingerfd880802018-11-08 17:41:54 -080041import com.android.internal.annotations.VisibleForTesting;
Brad Ebingerc5992532018-09-24 13:13:55 -070042import com.android.internal.telephony.ITelephony;
43
44import java.lang.annotation.Retention;
45import java.lang.annotation.RetentionPolicy;
Brad Ebingerfd880802018-11-08 17:41:54 -080046import java.util.HashMap;
47import java.util.Map;
Brad Ebingerc5992532018-09-24 13:13:55 -070048import java.util.concurrent.Executor;
49
50/**
51 * A manager for the MmTel (Multimedia Telephony) feature of an IMS network, given an associated
52 * subscription.
53 *
54 * Allows a user to query the IMS MmTel feature information for a subscription, register for
55 * registration and MmTel capability status callbacks, as well as query/modify user settings for the
56 * associated subscription.
57 *
Brad Ebinger5a8bb0a2019-01-14 15:44:45 -080058 * @see #createForSubscriptionId(int)
Brad Ebingerc5992532018-09-24 13:13:55 -070059 * @hide
60 */
Brad Ebingerfd880802018-11-08 17:41:54 -080061@SystemApi
Brad Ebingerc5992532018-09-24 13:13:55 -070062public class ImsMmTelManager {
63
64 private static final String TAG = "ImsMmTelManager";
65
66 /**
67 * @hide
68 */
69 @Retention(RetentionPolicy.SOURCE)
70 @IntDef(prefix = "WIFI_MODE_", value = {
71 WIFI_MODE_WIFI_ONLY,
72 WIFI_MODE_CELLULAR_PREFERRED,
73 WIFI_MODE_WIFI_PREFERRED
74 })
75 public @interface WiFiCallingMode {}
76
77 /**
78 * Register for IMS over IWLAN if WiFi signal quality is high enough. Do not hand over to LTE
79 * registration if signal quality degrades.
Brad Ebingerc5992532018-09-24 13:13:55 -070080 */
Brad Ebingerc5992532018-09-24 13:13:55 -070081 public static final int WIFI_MODE_WIFI_ONLY = 0;
82
83 /**
84 * Prefer registering for IMS over LTE if LTE signal quality is high enough.
Brad Ebingerc5992532018-09-24 13:13:55 -070085 */
Brad Ebingerc5992532018-09-24 13:13:55 -070086 public static final int WIFI_MODE_CELLULAR_PREFERRED = 1;
87
88 /**
89 * Prefer registering for IMS over IWLAN if possible if WiFi signal quality is high enough.
Brad Ebingerc5992532018-09-24 13:13:55 -070090 */
Brad Ebingerc5992532018-09-24 13:13:55 -070091 public static final int WIFI_MODE_WIFI_PREFERRED = 2;
92
93 /**
Brad Ebinger5eb12512019-01-09 16:21:50 -080094 * Callback class for receiving IMS network Registration callback events.
Brad Ebingerfd880802018-11-08 17:41:54 -080095 * @see #registerImsRegistrationCallback(Executor, RegistrationCallback) (RegistrationCallback)
96 * @see #unregisterImsRegistrationCallback(RegistrationCallback)
Brad Ebingerc5992532018-09-24 13:13:55 -070097 */
98 public static class RegistrationCallback {
99
100 private static class RegistrationBinder extends IImsRegistrationCallback.Stub {
101
Brad Ebingerfd880802018-11-08 17:41:54 -0800102 // Translate ImsRegistrationImplBase API to new AccessNetworkConstant because WLAN
103 // and WWAN are more accurate constants.
104 private static final Map<Integer, Integer> IMS_REG_TO_ACCESS_TYPE_MAP =
105 new HashMap<Integer, Integer>() {{
106 // Map NONE to -1 to make sure that we handle the REGISTRATION_TECH_NONE
107 // case, since it is defined.
108 put(ImsRegistrationImplBase.REGISTRATION_TECH_NONE, -1);
109 put(ImsRegistrationImplBase.REGISTRATION_TECH_LTE,
110 AccessNetworkConstants.TransportType.WWAN);
111 put(ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN,
112 AccessNetworkConstants.TransportType.WLAN);
113 }};
114
Brad Ebingerc5992532018-09-24 13:13:55 -0700115 private final RegistrationCallback mLocalCallback;
116 private Executor mExecutor;
117
118 RegistrationBinder(RegistrationCallback localCallback) {
119 mLocalCallback = localCallback;
120 }
121
122 @Override
123 public void onRegistered(int imsRadioTech) {
124 if (mLocalCallback == null) return;
125
Brad Ebingerfd880802018-11-08 17:41:54 -0800126 Binder.withCleanCallingIdentity(() -> mExecutor.execute(() ->
127 mLocalCallback.onRegistered(getAccessType(imsRadioTech))));
Brad Ebingerc5992532018-09-24 13:13:55 -0700128 }
129
130 @Override
131 public void onRegistering(int imsRadioTech) {
132 if (mLocalCallback == null) return;
133
Brad Ebingerfd880802018-11-08 17:41:54 -0800134 Binder.withCleanCallingIdentity(() -> mExecutor.execute(() ->
135 mLocalCallback.onRegistering(getAccessType(imsRadioTech))));
Brad Ebingerc5992532018-09-24 13:13:55 -0700136 }
137
138 @Override
139 public void onDeregistered(ImsReasonInfo info) {
140 if (mLocalCallback == null) return;
141
142 Binder.withCleanCallingIdentity(() ->
Brad Ebinger66cee392019-02-21 14:31:02 -0800143 mExecutor.execute(() -> mLocalCallback.onUnregistered(info)));
Brad Ebingerc5992532018-09-24 13:13:55 -0700144 }
145
146 @Override
147 public void onTechnologyChangeFailed(int imsRadioTech, ImsReasonInfo info) {
148 if (mLocalCallback == null) return;
149
150 Binder.withCleanCallingIdentity(() ->
Brad Ebingerfd880802018-11-08 17:41:54 -0800151 mExecutor.execute(() -> mLocalCallback.onTechnologyChangeFailed(
152 getAccessType(imsRadioTech), info)));
Brad Ebingerc5992532018-09-24 13:13:55 -0700153 }
154
155 @Override
156 public void onSubscriberAssociatedUriChanged(Uri[] uris) {
157 if (mLocalCallback == null) return;
158
159 Binder.withCleanCallingIdentity(() ->
160 mExecutor.execute(() ->
161 mLocalCallback.onSubscriberAssociatedUriChanged(uris)));
162 }
163
164 private void setExecutor(Executor executor) {
165 mExecutor = executor;
166 }
Brad Ebingerfd880802018-11-08 17:41:54 -0800167
168 private static int getAccessType(int regType) {
169 if (!IMS_REG_TO_ACCESS_TYPE_MAP.containsKey(regType)) {
170 Log.w("ImsMmTelManager", "RegistrationBinder - invalid regType returned: "
171 + regType);
172 return -1;
173 }
174 return IMS_REG_TO_ACCESS_TYPE_MAP.get(regType);
175 }
Brad Ebingerc5992532018-09-24 13:13:55 -0700176 }
177
178 private final RegistrationBinder mBinder = new RegistrationBinder(this);
179
180 /**
181 * Notifies the framework when the IMS Provider is registered to the IMS network.
182 *
Brad Ebingerfd880802018-11-08 17:41:54 -0800183 * @param imsTransportType the radio access technology. Valid values are defined in
184 * {@link android.telephony.AccessNetworkConstants.TransportType}.
Brad Ebingerc5992532018-09-24 13:13:55 -0700185 */
Brad Ebingerfd880802018-11-08 17:41:54 -0800186 public void onRegistered(int imsTransportType) {
Brad Ebingerc5992532018-09-24 13:13:55 -0700187 }
188
189 /**
190 * Notifies the framework when the IMS Provider is trying to register the IMS network.
191 *
Brad Ebingerfd880802018-11-08 17:41:54 -0800192 * @param imsTransportType the radio access technology. Valid values are defined in
193 * {@link android.telephony.AccessNetworkConstants.TransportType}.
Brad Ebingerc5992532018-09-24 13:13:55 -0700194 */
Brad Ebingerfd880802018-11-08 17:41:54 -0800195 public void onRegistering(int imsTransportType) {
Brad Ebingerc5992532018-09-24 13:13:55 -0700196 }
197
198 /**
199 * Notifies the framework when the IMS Provider is deregistered from the IMS network.
200 *
201 * @param info the {@link ImsReasonInfo} associated with why registration was disconnected.
202 */
Brad Ebingeraec46b12019-02-28 13:10:32 -0800203 public void onUnregistered(@Nullable ImsReasonInfo info) {
Brad Ebingerc5992532018-09-24 13:13:55 -0700204 }
205
206 /**
207 * A failure has occurred when trying to handover registration to another technology type,
Brad Ebingerfd880802018-11-08 17:41:54 -0800208 * defined in {@link android.telephony.AccessNetworkConstants.TransportType}
Brad Ebingerc5992532018-09-24 13:13:55 -0700209 *
Brad Ebingerfd880802018-11-08 17:41:54 -0800210 * @param imsTransportType The
211 * {@link android.telephony.AccessNetworkConstants.TransportType}
212 * transport type that has failed to handover registration to.
Brad Ebingerc5992532018-09-24 13:13:55 -0700213 * @param info A {@link ImsReasonInfo} that identifies the reason for failure.
214 */
Brad Ebingeraec46b12019-02-28 13:10:32 -0800215 public void onTechnologyChangeFailed(int imsTransportType, @Nullable ImsReasonInfo info) {
Brad Ebingerc5992532018-09-24 13:13:55 -0700216 }
217
218 /**
219 * Returns a list of subscriber {@link Uri}s associated with this IMS subscription when
220 * it changes. Per RFC3455, an associated URI is a URI that the service provider has
221 * allocated to a user for their own usage. A user's phone number is typically one of the
222 * associated URIs.
223 * @param uris new array of subscriber {@link Uri}s that are associated with this IMS
224 * subscription.
225 * @hide
226 */
Brad Ebingeraec46b12019-02-28 13:10:32 -0800227 public void onSubscriberAssociatedUriChanged(@Nullable Uri[] uris) {
Brad Ebingerc5992532018-09-24 13:13:55 -0700228 }
229
230 /**@hide*/
231 public final IImsRegistrationCallback getBinder() {
232 return mBinder;
233 }
234
235 /**@hide*/
236 //Only exposed as public for compatibility with deprecated ImsManager APIs.
237 public void setExecutor(Executor executor) {
238 mBinder.setExecutor(executor);
239 }
240 }
241
242 /**
Brad Ebinger5eb12512019-01-09 16:21:50 -0800243 * Receives IMS capability status updates from the ImsService. This information is also
244 * available via the {@link #isAvailable(int, int)} method below.
Brad Ebingerc5992532018-09-24 13:13:55 -0700245 *
Brad Ebingerfd880802018-11-08 17:41:54 -0800246 * @see #registerMmTelCapabilityCallback(Executor, CapabilityCallback) (CapabilityCallback)
247 * @see #unregisterMmTelCapabilityCallback(CapabilityCallback)
Brad Ebingerc5992532018-09-24 13:13:55 -0700248 */
249 public static class CapabilityCallback {
250
251 private static class CapabilityBinder extends IImsCapabilityCallback.Stub {
252
253 private final CapabilityCallback mLocalCallback;
254 private Executor mExecutor;
255
256 CapabilityBinder(CapabilityCallback c) {
257 mLocalCallback = c;
258 }
259
260 @Override
261 public void onCapabilitiesStatusChanged(int config) {
262 if (mLocalCallback == null) return;
263
264 Binder.withCleanCallingIdentity(() ->
265 mExecutor.execute(() -> mLocalCallback.onCapabilitiesStatusChanged(
266 new MmTelFeature.MmTelCapabilities(config))));
267 }
268
269 @Override
270 public void onQueryCapabilityConfiguration(int capability, int radioTech,
271 boolean isEnabled) {
272 // This is not used for public interfaces.
273 }
274
275 @Override
276 public void onChangeCapabilityConfigurationError(int capability, int radioTech,
277 @ImsFeature.ImsCapabilityError int reason) {
278 // This is not used for public interfaces
279 }
280
281 private void setExecutor(Executor executor) {
282 mExecutor = executor;
283 }
284 }
285
286 private final CapabilityBinder mBinder = new CapabilityBinder(this);
287
288 /**
289 * The status of the feature's capabilities has changed to either available or unavailable.
290 * If unavailable, the feature is not able to support the unavailable capability at this
291 * time.
292 *
Brad Ebinger5eb12512019-01-09 16:21:50 -0800293 * This information can also be queried using the {@link #isAvailable(int, int)} API.
294 *
Brad Ebingerc5992532018-09-24 13:13:55 -0700295 * @param capabilities The new availability of the capabilities.
296 */
297 public void onCapabilitiesStatusChanged(
Brad Ebingeraec46b12019-02-28 13:10:32 -0800298 @NonNull MmTelFeature.MmTelCapabilities capabilities) {
Brad Ebingerc5992532018-09-24 13:13:55 -0700299 }
300
301 /**@hide*/
302 public final IImsCapabilityCallback getBinder() {
303 return mBinder;
304 }
305
306 /**@hide*/
307 // Only exposed as public method for compatibility with deprecated ImsManager APIs.
308 // TODO: clean up dependencies and change back to private visibility.
Brad Ebinger5eb12512019-01-09 16:21:50 -0800309 public final void setExecutor(Executor executor) {
Brad Ebingerc5992532018-09-24 13:13:55 -0700310 mBinder.setExecutor(executor);
311 }
312 }
313
Brad Ebingerc5992532018-09-24 13:13:55 -0700314 private int mSubId;
315
316 /**
317 * Create an instance of ImsManager for the subscription id specified.
318 *
Brad Ebinger0d36ed22018-10-31 11:22:26 -0700319 * @param subId The ID of the subscription that this ImsMmTelManager will use.
Brad Ebingerc5992532018-09-24 13:13:55 -0700320 * @see android.telephony.SubscriptionManager#getActiveSubscriptionInfoList()
Brad Ebinger5a8bb0a2019-01-14 15:44:45 -0800321 * @throws IllegalArgumentException if the subscription is invalid.
Brad Ebingerc5992532018-09-24 13:13:55 -0700322 */
Brad Ebingeraec46b12019-02-28 13:10:32 -0800323 public static @NonNull ImsMmTelManager createForSubscriptionId(int subId) {
Brad Ebinger5a8bb0a2019-01-14 15:44:45 -0800324 if (!SubscriptionManager.isValidSubscriptionId(subId)) {
Brad Ebingerc5992532018-09-24 13:13:55 -0700325 throw new IllegalArgumentException("Invalid subscription ID");
326 }
327
Brad Ebingerfd880802018-11-08 17:41:54 -0800328 return new ImsMmTelManager(subId);
Brad Ebingerc5992532018-09-24 13:13:55 -0700329 }
330
Brad Ebingerfd880802018-11-08 17:41:54 -0800331 /**
Brad Ebinger5a8bb0a2019-01-14 15:44:45 -0800332 * Only visible for testing, use {@link #createForSubscriptionId(int)} instead.
Brad Ebingerfd880802018-11-08 17:41:54 -0800333 * @hide
334 */
335 @VisibleForTesting
336 public ImsMmTelManager(int subId) {
Brad Ebingerc5992532018-09-24 13:13:55 -0700337 mSubId = subId;
338 }
339
340 /**
341 * Registers a {@link RegistrationCallback} with the system, which will provide registration
Brad Ebinger5a8bb0a2019-01-14 15:44:45 -0800342 * updates for the subscription specified in {@link #createForSubscriptionId(int)}. Use
Brad Ebingerc5992532018-09-24 13:13:55 -0700343 * {@link SubscriptionManager.OnSubscriptionsChangedListener} to listen to Subscription changed
Brad Ebinger5eb12512019-01-09 16:21:50 -0800344 * events and call {@link #unregisterImsRegistrationCallback(RegistrationCallback)} to clean up.
Brad Ebingerfd880802018-11-08 17:41:54 -0800345 *
346 * When the callback is registered, it will initiate the callback c to be called with the
347 * current registration state.
348 *
Brad Ebingerc5992532018-09-24 13:13:55 -0700349 * @param executor The executor the callback events should be run on.
350 * @param c The {@link RegistrationCallback} to be added.
Brad Ebingerfd880802018-11-08 17:41:54 -0800351 * @see #unregisterImsRegistrationCallback(RegistrationCallback)
Brad Ebinger5eb12512019-01-09 16:21:50 -0800352 * @throws IllegalArgumentException if the subscription associated with this callback is not
353 * active (SIM is not inserted, ESIM inactive) or invalid, or a null {@link Executor} or
354 * {@link CapabilityCallback} callback.
Brad Ebinger5a8bb0a2019-01-14 15:44:45 -0800355 * @throws ImsException if the subscription associated with this callback is valid, but
Brad Ebinger5eb12512019-01-09 16:21:50 -0800356 * the {@link ImsService} associated with the subscription is not available. This can happen if
Brad Ebinger5a8bb0a2019-01-14 15:44:45 -0800357 * the service crashed, for example. See {@link ImsException#getCode()} for a more detailed
358 * reason.
Brad Ebingerc5992532018-09-24 13:13:55 -0700359 */
Brad Ebingerfd880802018-11-08 17:41:54 -0800360 @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
Brad Ebingeraec46b12019-02-28 13:10:32 -0800361 public void registerImsRegistrationCallback(@NonNull @CallbackExecutor Executor executor,
Brad Ebinger5a8bb0a2019-01-14 15:44:45 -0800362 @NonNull RegistrationCallback c) throws ImsException {
Brad Ebingerc5992532018-09-24 13:13:55 -0700363 if (c == null) {
364 throw new IllegalArgumentException("Must include a non-null RegistrationCallback.");
365 }
366 if (executor == null) {
367 throw new IllegalArgumentException("Must include a non-null Executor.");
368 }
369 c.setExecutor(executor);
370 try {
Brad Ebingerfd880802018-11-08 17:41:54 -0800371 getITelephony().registerImsRegistrationCallback(mSubId, c.getBinder());
Brad Ebingerc5992532018-09-24 13:13:55 -0700372 } catch (RemoteException e) {
373 throw e.rethrowAsRuntimeException();
Brad Ebinger5a8bb0a2019-01-14 15:44:45 -0800374 } catch (IllegalStateException e) {
375 throw new ImsException(e.getMessage(), ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
Brad Ebingerc5992532018-09-24 13:13:55 -0700376 }
377 }
378
379 /**
Brad Ebinger5eb12512019-01-09 16:21:50 -0800380 * Removes an existing {@link RegistrationCallback}.
381 *
382 * When the subscription associated with this callback is removed (SIM removed, ESIM swap,
383 * etc...), this callback will automatically be removed. If this method is called for an
384 * inactive subscription, it will result in a no-op.
385 *
Brad Ebingerc5992532018-09-24 13:13:55 -0700386 * @param c The {@link RegistrationCallback} to be removed.
387 * @see SubscriptionManager.OnSubscriptionsChangedListener
Brad Ebingerfd880802018-11-08 17:41:54 -0800388 * @see #registerImsRegistrationCallback(Executor, RegistrationCallback)
Brad Ebinger5eb12512019-01-09 16:21:50 -0800389 * @throws IllegalArgumentException if the subscription ID associated with this callback is
390 * invalid.
Brad Ebingerc5992532018-09-24 13:13:55 -0700391 */
Brad Ebingerfd880802018-11-08 17:41:54 -0800392 @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
393 public void unregisterImsRegistrationCallback(@NonNull RegistrationCallback c) {
Brad Ebingerc5992532018-09-24 13:13:55 -0700394 if (c == null) {
395 throw new IllegalArgumentException("Must include a non-null RegistrationCallback.");
396 }
397 try {
Brad Ebingerfd880802018-11-08 17:41:54 -0800398 getITelephony().unregisterImsRegistrationCallback(mSubId, c.getBinder());
Brad Ebingerc5992532018-09-24 13:13:55 -0700399 } catch (RemoteException e) {
400 throw e.rethrowAsRuntimeException();
401 }
402 }
403
404 /**
Brad Ebinger5eb12512019-01-09 16:21:50 -0800405 * Registers a {@link CapabilityCallback} with the system, which will provide MmTel service
406 * availability updates for the subscription specified in
Brad Ebinger5a8bb0a2019-01-14 15:44:45 -0800407 * {@link #createForSubscriptionId(int)}. The method {@link #isAvailable(int, int)}
Brad Ebinger5eb12512019-01-09 16:21:50 -0800408 * can also be used to query this information at any time.
409 *
Brad Ebingerc5992532018-09-24 13:13:55 -0700410 * Use {@link SubscriptionManager.OnSubscriptionsChangedListener} to listen to
411 * subscription changed events and call
Brad Ebinger5eb12512019-01-09 16:21:50 -0800412 * {@link #unregisterImsRegistrationCallback(RegistrationCallback)} to clean up.
Brad Ebingerfd880802018-11-08 17:41:54 -0800413 *
414 * When the callback is registered, it will initiate the callback c to be called with the
415 * current capabilities.
416 *
Brad Ebingerc5992532018-09-24 13:13:55 -0700417 * @param executor The executor the callback events should be run on.
418 * @param c The MmTel {@link CapabilityCallback} to be registered.
Brad Ebingerfd880802018-11-08 17:41:54 -0800419 * @see #unregisterMmTelCapabilityCallback(CapabilityCallback)
Brad Ebinger5eb12512019-01-09 16:21:50 -0800420 * @throws IllegalArgumentException if the subscription associated with this callback is not
421 * active (SIM is not inserted, ESIM inactive) or invalid, or a null {@link Executor} or
422 * {@link CapabilityCallback} callback.
Brad Ebinger5a8bb0a2019-01-14 15:44:45 -0800423 * @throws ImsException if the subscription associated with this callback is valid, but
Brad Ebinger5eb12512019-01-09 16:21:50 -0800424 * the {@link ImsService} associated with the subscription is not available. This can happen if
Brad Ebinger5a8bb0a2019-01-14 15:44:45 -0800425 * the service crashed, for example. See {@link ImsException#getCode()} for a more detailed
426 * reason.
Brad Ebingerc5992532018-09-24 13:13:55 -0700427 */
Brad Ebingerfd880802018-11-08 17:41:54 -0800428 @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
Brad Ebinger5eb12512019-01-09 16:21:50 -0800429 public void registerMmTelCapabilityCallback(@NonNull @CallbackExecutor Executor executor,
Brad Ebinger5a8bb0a2019-01-14 15:44:45 -0800430 @NonNull CapabilityCallback c) throws ImsException {
Brad Ebingerc5992532018-09-24 13:13:55 -0700431 if (c == null) {
432 throw new IllegalArgumentException("Must include a non-null RegistrationCallback.");
433 }
434 if (executor == null) {
435 throw new IllegalArgumentException("Must include a non-null Executor.");
436 }
437 c.setExecutor(executor);
438 try {
Brad Ebingerfd880802018-11-08 17:41:54 -0800439 getITelephony().registerMmTelCapabilityCallback(mSubId, c.getBinder());
Brad Ebingerc5992532018-09-24 13:13:55 -0700440 } catch (RemoteException e) {
441 throw e.rethrowAsRuntimeException();
Brad Ebinger5a8bb0a2019-01-14 15:44:45 -0800442 } catch (IllegalStateException e) {
443 throw new ImsException(e.getMessage(), ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
Brad Ebingerc5992532018-09-24 13:13:55 -0700444 }
445 }
446
447 /**
Brad Ebinger5eb12512019-01-09 16:21:50 -0800448 * Removes an existing MmTel {@link CapabilityCallback}.
449 *
450 * When the subscription associated with this callback is removed (SIM removed, ESIM swap,
451 * etc...), this callback will automatically be removed. If this method is called for an
452 * inactive subscription, it will result in a no-op.
Brad Ebingerc5992532018-09-24 13:13:55 -0700453 * @param c The MmTel {@link CapabilityCallback} to be removed.
Brad Ebingerfd880802018-11-08 17:41:54 -0800454 * @see #registerMmTelCapabilityCallback(Executor, CapabilityCallback)
Brad Ebinger5eb12512019-01-09 16:21:50 -0800455 * @throws IllegalArgumentException if the subscription ID associated with this callback is
456 * invalid.
Brad Ebingerc5992532018-09-24 13:13:55 -0700457 */
Brad Ebingerfd880802018-11-08 17:41:54 -0800458 @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
459 public void unregisterMmTelCapabilityCallback(@NonNull CapabilityCallback c) {
Brad Ebingerc5992532018-09-24 13:13:55 -0700460 if (c == null) {
461 throw new IllegalArgumentException("Must include a non-null RegistrationCallback.");
462 }
463 try {
Brad Ebingerfd880802018-11-08 17:41:54 -0800464 getITelephony().unregisterMmTelCapabilityCallback(mSubId, c.getBinder());
Brad Ebingerc5992532018-09-24 13:13:55 -0700465 } catch (RemoteException e) {
466 throw e.rethrowAsRuntimeException();
467 }
468 }
469
470 /**
Brad Ebingerfd880802018-11-08 17:41:54 -0800471 * Query the user’s setting for “Advanced Calling” or "Enhanced 4G LTE", which is used to
472 * enable MmTel IMS features, depending on the carrier configuration for the current
473 * subscription. If this setting is enabled, IMS voice and video telephony over IWLAN/LTE will
474 * be enabled as long as the carrier has provisioned these services for the specified
475 * subscription. Other IMS services (SMS/UT) are not affected by this user setting and depend on
476 * carrier requirements.
477 *
478 * Modifying this value may also trigger an IMS registration or deregistration, depending on
479 * whether or not the new value is enabled or disabled.
480 *
481 * Note: If the carrier configuration for advanced calling is not editable or hidden, this
482 * method will do nothing and will instead always use the default value.
483 *
484 * @see android.telephony.CarrierConfigManager#KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL
485 * @see android.telephony.CarrierConfigManager#KEY_EDITABLE_ENHANCED_4G_LTE_BOOL
486 * @see android.telephony.CarrierConfigManager#KEY_HIDE_ENHANCED_4G_LTE_BOOL
487 * @see android.telephony.CarrierConfigManager#KEY_ENHANCED_4G_LTE_ON_BY_DEFAULT_BOOL
488 * @see android.telephony.CarrierConfigManager#KEY_CARRIER_VOLTE_AVAILABLE_BOOL
Brad Ebinger66cee392019-02-21 14:31:02 -0800489 * @see #setAdvancedCallingSettingEnabled(boolean)
Brad Ebingerfd880802018-11-08 17:41:54 -0800490 * @return true if the user's setting for advanced calling is enabled, false otherwise.
Brad Ebingerc5992532018-09-24 13:13:55 -0700491 */
Brad Ebingerc5992532018-09-24 13:13:55 -0700492 @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
493 public boolean isAdvancedCallingSettingEnabled() {
494 try {
495 return getITelephony().isAdvancedCallingSettingEnabled(mSubId);
496 } catch (RemoteException e) {
497 throw e.rethrowAsRuntimeException();
498 }
499 }
500
501 /**
502 * Modify the user’s setting for “Advanced Calling” or "Enhanced 4G LTE", which is used to
Brad Ebingerfd880802018-11-08 17:41:54 -0800503 * enable MmTel IMS features, depending on the carrier configuration for the current
504 * subscription. If this setting is enabled, IMS voice and video telephony over IWLAN/LTE will
505 * be enabled as long as the carrier has provisioned these services for the specified
506 * subscription. Other IMS services (SMS/UT) are not affected by this user setting and depend on
507 * carrier requirements.
508 *
509 * Modifying this value may also trigger an IMS registration or deregistration, depending on
510 * whether or not the new value is enabled or disabled.
511 *
512 * Note: If the carrier configuration for advanced calling is not editable or hidden, this
513 * method will do nothing and will instead always use the default value.
514 *
515 * @see android.telephony.CarrierConfigManager#KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL
516 * @see android.telephony.CarrierConfigManager#KEY_EDITABLE_ENHANCED_4G_LTE_BOOL
517 * @see android.telephony.CarrierConfigManager#KEY_HIDE_ENHANCED_4G_LTE_BOOL
518 * @see android.telephony.CarrierConfigManager#KEY_ENHANCED_4G_LTE_ON_BY_DEFAULT_BOOL
519 * @see android.telephony.CarrierConfigManager#KEY_CARRIER_VOLTE_AVAILABLE_BOOL
520 * @see #isAdvancedCallingSettingEnabled()
Brad Ebingerc5992532018-09-24 13:13:55 -0700521 */
Brad Ebingerc5992532018-09-24 13:13:55 -0700522 @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
Brad Ebinger66cee392019-02-21 14:31:02 -0800523 public void setAdvancedCallingSettingEnabled(boolean isEnabled) {
Brad Ebingerc5992532018-09-24 13:13:55 -0700524 try {
Brad Ebinger66cee392019-02-21 14:31:02 -0800525 getITelephony().setAdvancedCallingSettingEnabled(mSubId, isEnabled);
Brad Ebingerc5992532018-09-24 13:13:55 -0700526 return;
527 } catch (RemoteException e) {
528 throw e.rethrowAsRuntimeException();
529 }
530 }
531
532 /**
533 * Query the IMS MmTel capability for a given registration technology. This does not
534 * necessarily mean that we are registered and the capability is available, but rather the
535 * subscription is capable of this service over IMS.
536 *
537 * @see android.telephony.CarrierConfigManager#KEY_CARRIER_VOLTE_AVAILABLE_BOOL
538 * @see android.telephony.CarrierConfigManager#KEY_CARRIER_VT_AVAILABLE_BOOL
539 * @see android.telephony.CarrierConfigManager#KEY_CARRIER_IMS_GBA_REQUIRED_BOOL
540 * @see #isAvailable(int, int)
541 *
542 * @param imsRegTech The IMS registration technology, can be one of the following:
543 * {@link ImsRegistrationImplBase#REGISTRATION_TECH_LTE},
544 * {@link ImsRegistrationImplBase#REGISTRATION_TECH_IWLAN}
545 * @param capability The IMS MmTel capability to query, can be one of the following:
546 * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_VOICE},
547 * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_VIDEO,
548 * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_UT},
549 * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_SMS}
550 * @return {@code true} if the MmTel IMS capability is capable for this subscription, false
551 * otherwise.
552 */
Brad Ebingerfd880802018-11-08 17:41:54 -0800553 @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
Brad Ebingerc5992532018-09-24 13:13:55 -0700554 public boolean isCapable(@MmTelFeature.MmTelCapabilities.MmTelCapability int capability,
555 @ImsRegistrationImplBase.ImsRegistrationTech int imsRegTech) {
556 try {
Brad Ebingerfd880802018-11-08 17:41:54 -0800557 return getITelephony().isCapable(mSubId, capability, imsRegTech);
Brad Ebingerc5992532018-09-24 13:13:55 -0700558 } catch (RemoteException e) {
559 throw e.rethrowAsRuntimeException();
560 }
561 }
562
563 /**
564 * Query the availability of an IMS MmTel capability for a given registration technology. If
565 * a capability is available, IMS is registered and the service is currently available over IMS.
566 *
567 * @see #isCapable(int, int)
568 *
569 * @param imsRegTech The IMS registration technology, can be one of the following:
570 * {@link ImsRegistrationImplBase#REGISTRATION_TECH_LTE},
571 * {@link ImsRegistrationImplBase#REGISTRATION_TECH_IWLAN}
572 * @param capability The IMS MmTel capability to query, can be one of the following:
573 * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_VOICE},
574 * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_VIDEO,
575 * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_UT},
576 * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_SMS}
577 * @return {@code true} if the MmTel IMS capability is available for this subscription, false
578 * otherwise.
579 */
Brad Ebingerfd880802018-11-08 17:41:54 -0800580 @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
Brad Ebingerc5992532018-09-24 13:13:55 -0700581 public boolean isAvailable(@MmTelFeature.MmTelCapabilities.MmTelCapability int capability,
582 @ImsRegistrationImplBase.ImsRegistrationTech int imsRegTech) {
583 try {
Brad Ebingerfd880802018-11-08 17:41:54 -0800584 return getITelephony().isAvailable(mSubId, capability, imsRegTech);
Brad Ebingerc5992532018-09-24 13:13:55 -0700585 } catch (RemoteException e) {
586 throw e.rethrowAsRuntimeException();
587 }
588 }
589
590 /**
591 * The user's setting for whether or not they have enabled the "Video Calling" setting.
592 * @return true if the user’s “Video Calling” setting is currently enabled.
Brad Ebinger66cee392019-02-21 14:31:02 -0800593 * @see #setVtSettingEnabled(boolean)
Brad Ebingerc5992532018-09-24 13:13:55 -0700594 */
Brad Ebingerfd880802018-11-08 17:41:54 -0800595 @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
Brad Ebingerc5992532018-09-24 13:13:55 -0700596 public boolean isVtSettingEnabled() {
597 try {
Brad Ebingerfd880802018-11-08 17:41:54 -0800598 return getITelephony().isVtSettingEnabled(mSubId);
Brad Ebingerc5992532018-09-24 13:13:55 -0700599 } catch (RemoteException e) {
600 throw e.rethrowAsRuntimeException();
601 }
602 }
603
604 /**
605 * Change the user's setting for Video Telephony and enable the Video Telephony capability.
606 * @see #isVtSettingEnabled()
Brad Ebingerc5992532018-09-24 13:13:55 -0700607 */
Brad Ebingerc5992532018-09-24 13:13:55 -0700608 @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
Brad Ebinger66cee392019-02-21 14:31:02 -0800609 public void setVtSettingEnabled(boolean isEnabled) {
Brad Ebingerc5992532018-09-24 13:13:55 -0700610 try {
Brad Ebinger66cee392019-02-21 14:31:02 -0800611 getITelephony().setVtSettingEnabled(mSubId, isEnabled);
Brad Ebingerc5992532018-09-24 13:13:55 -0700612 return;
613 } catch (RemoteException e) {
614 throw e.rethrowAsRuntimeException();
615 }
616 }
617
618 /**
619 * @return true if the user's setting for Voice over WiFi is enabled and false if it is not.
Brad Ebinger66cee392019-02-21 14:31:02 -0800620 * @see #setVoWiFiSettingEnabled(boolean)
Brad Ebingerc5992532018-09-24 13:13:55 -0700621 */
Brad Ebingerc5992532018-09-24 13:13:55 -0700622 @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
623 public boolean isVoWiFiSettingEnabled() {
624 try {
625 return getITelephony().isVoWiFiSettingEnabled(mSubId);
626 } catch (RemoteException e) {
627 throw e.rethrowAsRuntimeException();
628 }
629 }
630
631 /**
632 * Sets the user's setting for whether or not Voice over WiFi is enabled.
633 * @param isEnabled true if the user's setting for Voice over WiFi is enabled, false otherwise=
634 * @see #isVoWiFiSettingEnabled()
Brad Ebingerc5992532018-09-24 13:13:55 -0700635 */
Brad Ebingerc5992532018-09-24 13:13:55 -0700636 @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
Brad Ebinger66cee392019-02-21 14:31:02 -0800637 public void setVoWiFiSettingEnabled(boolean isEnabled) {
Brad Ebingerc5992532018-09-24 13:13:55 -0700638 try {
Brad Ebinger66cee392019-02-21 14:31:02 -0800639 getITelephony().setVoWiFiSettingEnabled(mSubId, isEnabled);
Brad Ebingerc5992532018-09-24 13:13:55 -0700640 return;
641 } catch (RemoteException e) {
642 throw e.rethrowAsRuntimeException();
643 }
644 }
645
646 /**
647 * @return true if the user's setting for Voice over WiFi while roaming is enabled, false
648 * if disabled.
Brad Ebinger66cee392019-02-21 14:31:02 -0800649 * @see #setVoWiFiRoamingSettingEnabled(boolean)
Brad Ebingerc5992532018-09-24 13:13:55 -0700650 */
Brad Ebingerc5992532018-09-24 13:13:55 -0700651 @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
652 public boolean isVoWiFiRoamingSettingEnabled() {
653 try {
654 return getITelephony().isVoWiFiRoamingSettingEnabled(mSubId);
655 } catch (RemoteException e) {
656 throw e.rethrowAsRuntimeException();
657 }
658 }
659
660 /**
661 * Change the user's setting for Voice over WiFi while roaming.
662 * @param isEnabled true if the user's setting for Voice over WiFi while roaming is enabled,
663 * false otherwise.
664 * @see #isVoWiFiRoamingSettingEnabled()
Brad Ebingerc5992532018-09-24 13:13:55 -0700665 */
Brad Ebingerc5992532018-09-24 13:13:55 -0700666 @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
Brad Ebinger66cee392019-02-21 14:31:02 -0800667 public void setVoWiFiRoamingSettingEnabled(boolean isEnabled) {
Brad Ebingerc5992532018-09-24 13:13:55 -0700668 try {
Brad Ebinger66cee392019-02-21 14:31:02 -0800669 getITelephony().setVoWiFiRoamingSettingEnabled(mSubId, isEnabled);
Brad Ebingerc5992532018-09-24 13:13:55 -0700670 return;
671 } catch (RemoteException e) {
672 throw e.rethrowAsRuntimeException();
673 }
674 }
675
676 /**
677 * Overrides the Voice over WiFi capability to true for IMS, but do not persist the setting.
678 * Typically used during the Voice over WiFi registration process for some carriers.
679 *
680 * @param isCapable true if the IMS stack should try to register for IMS over IWLAN, false
681 * otherwise.
682 * @param mode the Voice over WiFi mode preference to set, which can be one of the following:
683 * - {@link #WIFI_MODE_WIFI_ONLY}
684 * - {@link #WIFI_MODE_CELLULAR_PREFERRED}
685 * - {@link #WIFI_MODE_WIFI_PREFERRED}
Brad Ebinger66cee392019-02-21 14:31:02 -0800686 * @see #setVoWiFiSettingEnabled(boolean)
Brad Ebingerc5992532018-09-24 13:13:55 -0700687 */
Brad Ebingerc5992532018-09-24 13:13:55 -0700688 @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
689 public void setVoWiFiNonPersistent(boolean isCapable, int mode) {
690 try {
691 getITelephony().setVoWiFiNonPersistent(mSubId, isCapable, mode);
692 return;
693 } catch (RemoteException e) {
694 throw e.rethrowAsRuntimeException();
695 }
696 }
697
698 /**
699 * @return The Voice over WiFi Mode preference set by the user, which can be one of the
700 * following:
701 * - {@link #WIFI_MODE_WIFI_ONLY}
702 * - {@link #WIFI_MODE_CELLULAR_PREFERRED}
703 * - {@link #WIFI_MODE_WIFI_PREFERRED}
Brad Ebinger66cee392019-02-21 14:31:02 -0800704 * @see #setVoWiFiSettingEnabled(boolean)
Brad Ebingerc5992532018-09-24 13:13:55 -0700705 */
Brad Ebingerc5992532018-09-24 13:13:55 -0700706 @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
707 public @WiFiCallingMode int getVoWiFiModeSetting() {
708 try {
709 return getITelephony().getVoWiFiModeSetting(mSubId);
710 } catch (RemoteException e) {
711 throw e.rethrowAsRuntimeException();
712 }
713 }
714
715 /**
716 * Set the user's preference for Voice over WiFi calling mode.
717 * @param mode The user's preference for the technology to register for IMS over, can be one of
718 * the following:
719 * - {@link #WIFI_MODE_WIFI_ONLY}
720 * - {@link #WIFI_MODE_CELLULAR_PREFERRED}
721 * - {@link #WIFI_MODE_WIFI_PREFERRED}
722 * @see #getVoWiFiModeSetting()
Brad Ebingerc5992532018-09-24 13:13:55 -0700723 */
Brad Ebingerc5992532018-09-24 13:13:55 -0700724 @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
725 public void setVoWiFiModeSetting(@WiFiCallingMode int mode) {
726 try {
727 getITelephony().setVoWiFiModeSetting(mSubId, mode);
728 return;
729 } catch (RemoteException e) {
730 throw e.rethrowAsRuntimeException();
731 }
732 }
733
734 /**
735 * Set the user's preference for Voice over WiFi calling mode while the device is roaming on
736 * another network.
737 *
738 * @return The user's preference for the technology to register for IMS over when roaming on
739 * another network, can be one of the following:
740 * - {@link #WIFI_MODE_WIFI_ONLY}
741 * - {@link #WIFI_MODE_CELLULAR_PREFERRED}
742 * - {@link #WIFI_MODE_WIFI_PREFERRED}
Brad Ebinger66cee392019-02-21 14:31:02 -0800743 * @see #setVoWiFiRoamingSettingEnabled(boolean)
Brad Ebingerc5992532018-09-24 13:13:55 -0700744 */
Brad Ebingerc5992532018-09-24 13:13:55 -0700745 @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
Brad Ebinger6efd8832019-01-08 15:54:33 -0800746 public @WiFiCallingMode int getVoWiFiRoamingModeSetting() {
Brad Ebingerc5992532018-09-24 13:13:55 -0700747 try {
748 return getITelephony().getVoWiFiRoamingModeSetting(mSubId);
749 } catch (RemoteException e) {
750 throw e.rethrowAsRuntimeException();
751 }
752 }
753
754 /**
755 * Set the user's preference for Voice over WiFi mode while the device is roaming on another
756 * network.
757 *
758 * @param mode The user's preference for the technology to register for IMS over when roaming on
759 * another network, can be one of the following:
760 * - {@link #WIFI_MODE_WIFI_ONLY}
761 * - {@link #WIFI_MODE_CELLULAR_PREFERRED}
762 * - {@link #WIFI_MODE_WIFI_PREFERRED}
763 * @see #getVoWiFiRoamingModeSetting()
Brad Ebingerc5992532018-09-24 13:13:55 -0700764 */
Brad Ebingerc5992532018-09-24 13:13:55 -0700765 @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
766 public void setVoWiFiRoamingModeSetting(@WiFiCallingMode int mode) {
767 try {
768 getITelephony().setVoWiFiRoamingModeSetting(mSubId, mode);
769 return;
770 } catch (RemoteException e) {
771 throw e.rethrowAsRuntimeException();
772 }
773 }
774
775 /**
776 * Change the user's setting for RTT capability of this device.
777 * @param isEnabled if true RTT will be enabled during calls.
Brad Ebingerc5992532018-09-24 13:13:55 -0700778 */
Brad Ebingerc5992532018-09-24 13:13:55 -0700779 @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
780 public void setRttCapabilitySetting(boolean isEnabled) {
781 try {
782 getITelephony().setRttCapabilitySetting(mSubId, isEnabled);
783 return;
784 } catch (RemoteException e) {
785 throw e.rethrowAsRuntimeException();
786 }
787 }
788
789 /**
790 * @return true if TTY over VoLTE is supported
791 * @see android.telecom.TelecomManager#getCurrentTtyMode
792 * @see android.telephony.CarrierConfigManager#KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL
Brad Ebingerc5992532018-09-24 13:13:55 -0700793 */
Brad Ebingerc5992532018-09-24 13:13:55 -0700794 @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
795 boolean isTtyOverVolteEnabled() {
796 try {
797 return getITelephony().isTtyOverVolteEnabled(mSubId);
798 } catch (RemoteException e) {
799 throw e.rethrowAsRuntimeException();
800 }
801 }
802
Brad Ebingerc5992532018-09-24 13:13:55 -0700803 private static ITelephony getITelephony() {
804 ITelephony binder = ITelephony.Stub.asInterface(
805 ServiceManager.getService(Context.TELEPHONY_SERVICE));
806 if (binder == null) {
807 throw new RuntimeException("Could not find Telephony Service.");
808 }
809 return binder;
810 }
811}