blob: 3a971cf448b8226b5c407260cefca5ca6d9a3f09 [file] [log] [blame]
Wink Savilleef36ef62014-06-11 08:39:38 -07001/*
2 * Copyright (c) 2013 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.ims;
18
Brad Ebinger172977a2018-01-16 09:36:56 -080019import android.annotation.Nullable;
Wink Savilleef36ef62014-06-11 08:39:38 -070020import android.app.PendingIntent;
21import android.content.Context;
Brad Ebinger172977a2018-01-16 09:36:56 -080022import android.os.Bundle;
Brad Ebinger6ddf28e2018-02-21 16:07:23 -080023import android.os.Handler;
Wink Savilleef36ef62014-06-11 08:39:38 -070024import android.os.IBinder;
Brad Ebinger6ddf28e2018-02-21 16:07:23 -080025import android.os.Looper;
Wink Savilleef36ef62014-06-11 08:39:38 -070026import android.os.Message;
Naveen Kalla525c3a22017-02-06 14:46:42 -080027import android.os.Parcel;
Jonathan Basseri2acea6f2015-07-01 15:00:38 -070028import android.os.PersistableBundle;
Wink Savilleef36ef62014-06-11 08:39:38 -070029import android.os.RemoteException;
Etan Cohenaf55a402014-09-04 22:34:41 -070030import android.os.SystemProperties;
Etan Cohen82f78122014-12-15 10:10:14 -080031import android.telecom.TelecomManager;
Junda Liue7663c02015-06-23 11:16:26 -070032import android.telephony.CarrierConfigManager;
Mohamed Abdalkadere1453f42018-01-19 19:48:31 -080033import android.telephony.ims.stub.ImsRegistrationImplBase;
Wink Savilleef36ef62014-06-11 08:39:38 -070034import android.telephony.Rlog;
Etan Cohen82f78122014-12-15 10:10:14 -080035import android.telephony.SubscriptionManager;
Etan Cohencfc784d2014-08-07 18:40:31 -070036import android.telephony.TelephonyManager;
Brad Ebinger190ed932018-01-23 13:41:32 -080037import android.telephony.ims.ImsCallProfile;
38import android.telephony.ims.ImsReasonInfo;
Brad Ebinger172977a2018-01-16 09:36:56 -080039import android.telephony.ims.aidl.IImsConfig;
40import android.telephony.ims.aidl.IImsSmsListener;
41import android.telephony.ims.feature.CapabilityChangeRequest;
42import android.telephony.ims.feature.ImsFeature;
43import android.telephony.ims.feature.MmTelFeature;
Hall Liue511a202017-08-17 15:49:58 -070044import android.util.Log;
Wink Savilleef36ef62014-06-11 08:39:38 -070045
46import com.android.ims.internal.IImsCallSession;
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -070047import com.android.ims.internal.IImsEcbm;
Tyler Gunn4d128b62016-04-13 15:44:38 -070048import com.android.ims.internal.IImsMultiEndpoint;
Wink Savilleef36ef62014-06-11 08:39:38 -070049import com.android.ims.internal.IImsUt;
Brad Ebinger190ed932018-01-23 13:41:32 -080050import android.telephony.ims.ImsCallSession;
Brad Ebinger16780ff2017-01-26 11:18:21 -080051import com.android.internal.annotations.VisibleForTesting;
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -050052
Jack Yu2f102bd2015-12-28 15:31:48 -080053import java.io.FileDescriptor;
54import java.io.PrintWriter;
Naveen Kalla525c3a22017-02-06 14:46:42 -080055import java.util.ArrayList;
Etan Cohend7727462014-07-12 14:54:10 -070056import java.util.HashMap;
Brad Ebinger16780ff2017-01-26 11:18:21 -080057import java.util.Set;
Malcolm Chen18837ff2017-10-25 17:05:41 -070058import java.util.concurrent.ConcurrentLinkedDeque;
Brad Ebinger44fd8af2017-12-14 14:24:02 -080059import java.util.concurrent.CopyOnWriteArraySet;
Etan Cohend7727462014-07-12 14:54:10 -070060
Wink Savilleef36ef62014-06-11 08:39:38 -070061/**
62 * Provides APIs for IMS services, such as initiating IMS calls, and provides access to
63 * the operator's IMS network. This class is the starting point for any IMS actions.
64 * You can acquire an instance of it with {@link #getInstance getInstance()}.</p>
65 * <p>The APIs in this class allows you to:</p>
66 *
67 * @hide
68 */
69public class ImsManager {
Etan Cohen19604c02014-08-11 14:32:57 -070070
Etan Cohenaf55a402014-09-04 22:34:41 -070071 /*
72 * Debug flag to override configuration flag
73 */
Etan Cohenb651fa52014-10-22 10:51:29 -070074 public static final String PROPERTY_DBG_VOLTE_AVAIL_OVERRIDE = "persist.dbg.volte_avail_ovr";
75 public static final int PROPERTY_DBG_VOLTE_AVAIL_OVERRIDE_DEFAULT = 0;
Etan Cohenea2b5832014-10-23 18:50:35 -070076 public static final String PROPERTY_DBG_VT_AVAIL_OVERRIDE = "persist.dbg.vt_avail_ovr";
77 public static final int PROPERTY_DBG_VT_AVAIL_OVERRIDE_DEFAULT = 0;
Etan Cohena00c9192014-12-23 15:02:29 -080078 public static final String PROPERTY_DBG_WFC_AVAIL_OVERRIDE = "persist.dbg.wfc_avail_ovr";
79 public static final int PROPERTY_DBG_WFC_AVAIL_OVERRIDE_DEFAULT = 0;
Meng Wang9352c432016-06-08 14:22:20 -070080 public static final String PROPERTY_DBG_ALLOW_IMS_OFF_OVERRIDE = "persist.dbg.allow_ims_off";
81 public static final int PROPERTY_DBG_ALLOW_IMS_OFF_OVERRIDE_DEFAULT = 0;
Etan Cohenaf55a402014-09-04 22:34:41 -070082
Wink Savilleef36ef62014-06-11 08:39:38 -070083 /**
Wink Savilleef36ef62014-06-11 08:39:38 -070084 * The result code to be sent back with the incoming call {@link PendingIntent}.
Brad Ebinger172977a2018-01-16 09:36:56 -080085 * @see #open(MmTelFeature.Listener)
Wink Savilleef36ef62014-06-11 08:39:38 -070086 */
87 public static final int INCOMING_CALL_RESULT_CODE = 101;
88
89 /**
90 * Key to retrieve the call ID from an incoming call intent.
Brad Ebinger172977a2018-01-16 09:36:56 -080091 * @see #open(MmTelFeature.Listener)
Wink Savilleef36ef62014-06-11 08:39:38 -070092 */
93 public static final String EXTRA_CALL_ID = "android:imsCallID";
94
95 /**
96 * Action to broadcast when ImsService is up.
97 * Internal use only.
Brad Ebinger16780ff2017-01-26 11:18:21 -080098 * @deprecated
Wink Savilleef36ef62014-06-11 08:39:38 -070099 * @hide
100 */
101 public static final String ACTION_IMS_SERVICE_UP =
102 "com.android.ims.IMS_SERVICE_UP";
103
104 /**
105 * Action to broadcast when ImsService is down.
106 * Internal use only.
Brad Ebinger16780ff2017-01-26 11:18:21 -0800107 * @deprecated
Wink Savilleef36ef62014-06-11 08:39:38 -0700108 * @hide
109 */
110 public static final String ACTION_IMS_SERVICE_DOWN =
111 "com.android.ims.IMS_SERVICE_DOWN";
112
113 /**
Pavel Zhamaitsiak0c2f15c2015-03-12 15:37:54 -0700114 * Action to broadcast when ImsService registration fails.
115 * Internal use only.
116 * @hide
117 */
118 public static final String ACTION_IMS_REGISTRATION_ERROR =
119 "com.android.ims.REGISTRATION_ERROR";
120
121 /**
Etan Cohend7727462014-07-12 14:54:10 -0700122 * Part of the ACTION_IMS_SERVICE_UP or _DOWN intents.
Etan Cohenabbd7882014-09-26 22:35:35 -0700123 * A long value; the phone ID corresponding to the IMS service coming up or down.
Etan Cohend7727462014-07-12 14:54:10 -0700124 * Internal use only.
125 * @hide
126 */
Etan Cohenabbd7882014-09-26 22:35:35 -0700127 public static final String EXTRA_PHONE_ID = "android:phone_id";
Etan Cohend7727462014-07-12 14:54:10 -0700128
129 /**
Wink Savilleef36ef62014-06-11 08:39:38 -0700130 * Action for the incoming call intent for the Phone app.
131 * Internal use only.
132 * @hide
133 */
134 public static final String ACTION_IMS_INCOMING_CALL =
135 "com.android.ims.IMS_INCOMING_CALL";
136
137 /**
138 * Part of the ACTION_IMS_INCOMING_CALL intents.
139 * An integer value; service identifier obtained from {@link ImsManager#open}.
140 * Internal use only.
141 * @hide
142 */
143 public static final String EXTRA_SERVICE_ID = "android:imsServiceId";
144
145 /**
146 * Part of the ACTION_IMS_INCOMING_CALL intents.
147 * An boolean value; Flag to indicate that the incoming call is a normal call or call for USSD.
148 * The value "true" indicates that the incoming call is for USSD.
149 * Internal use only.
150 * @hide
151 */
152 public static final String EXTRA_USSD = "android:ussd";
153
Shriram Ganeshd3adfad2015-05-31 10:06:15 -0700154 /**
155 * Part of the ACTION_IMS_INCOMING_CALL intents.
156 * A boolean value; Flag to indicate whether the call is an unknown
157 * dialing call. Such calls are originated by sending commands (like
158 * AT commands) directly to modem without Android involvement.
159 * Even though they are not incoming calls, they are propagated
160 * to Phone app using same ACTION_IMS_INCOMING_CALL intent.
161 * Internal use only.
162 * @hide
163 */
Anju Mathapati9c033792015-06-16 16:33:16 -0700164 public static final String EXTRA_IS_UNKNOWN_CALL = "android:isUnknown";
Shriram Ganeshd3adfad2015-05-31 10:06:15 -0700165
Malcolm Chen18837ff2017-10-25 17:05:41 -0700166 private static final int SYSTEM_PROPERTY_NOT_SET = -1;
167
168 // -1 indicates a subscriptionProperty value that is never set.
169 private static final int SUB_PROPERTY_NOT_INITIALIZED = -1;
170
Wink Savilleef36ef62014-06-11 08:39:38 -0700171 private static final String TAG = "ImsManager";
172 private static final boolean DBG = true;
173
Brad Ebinger6ddf28e2018-02-21 16:07:23 -0800174 /**
175 * Helper class for managing a connection to the ImsManager when the ImsService is unavailable
176 * or switches to another service.
177 */
178 public static class Connector extends Handler {
179 // Initial condition for ims connection retry.
180 private static final int IMS_RETRY_STARTING_TIMEOUT_MS = 500; // ms
181 // Ceiling bitshift amount for service query timeout, calculated as:
182 // 2^mImsServiceRetryCount * IMS_RETRY_STARTING_TIMEOUT_MS, where
183 // mImsServiceRetryCount ∊ [0, CEILING_SERVICE_RETRY_COUNT].
184 private static final int CEILING_SERVICE_RETRY_COUNT = 6;
185
186 private final Runnable mGetServiceRunnable = () -> {
187 try {
188 getImsService();
189 } catch (ImsException e) {
190 retryGetImsService();
191 }
192 };
193
194 public interface Listener {
195 /**
196 * ImsManager is connected to the underlying IMS implementation.
197 */
198 void connectionReady(ImsManager manager) throws ImsException;
199
200 /**
201 * The underlying IMS implementation is unavailable and can not be used to communicate.
202 */
203 void connectionUnavailable();
204 }
205
206 @VisibleForTesting
207 public interface RetryTimeout {
208 int get();
209 }
210
211 // Callback fires when ImsManager MMTel Feature changes state
212 private MmTelFeatureConnection.IFeatureUpdate mNotifyStatusChangedCallback =
213 new MmTelFeatureConnection.IFeatureUpdate() {
214 @Override
215 public void notifyStateChanged() {
216 try {
217 int status = ImsFeature.STATE_UNAVAILABLE;
218 synchronized (mLock) {
219 if (mImsManager != null) {
220 status = mImsManager.getImsServiceState();
221 }
222 }
223 log("Status Changed: " + status);
224 switch (status) {
225 case ImsFeature.STATE_READY: {
226 notifyReady();
227 break;
228 }
229 case ImsFeature.STATE_INITIALIZING:
230 // fall through
231 case ImsFeature.STATE_UNAVAILABLE: {
232 notifyNotReady();
233 break;
234 }
235 default: {
236 Log.w(TAG, "Unexpected State!");
237 }
238 }
239 } catch (ImsException e) {
240 // Could not get the ImsService, retry!
241 notifyNotReady();
242 retryGetImsService();
243 }
244 }
245
246 @Override
247 public void notifyUnavailable() {
248 notifyNotReady();
249 retryGetImsService();
250 }
251 };
252
253 private final Context mContext;
254 private final int mPhoneId;
255 private final Listener mListener;
256 private final Object mLock = new Object();
257
258 private int mRetryCount = 0;
259 private ImsManager mImsManager;
260
261 @VisibleForTesting
262 public RetryTimeout mRetryTimeout = () -> {
263 synchronized (mLock) {
264 int timeout = (1 << mRetryCount) * IMS_RETRY_STARTING_TIMEOUT_MS;
265 if (mRetryCount <= CEILING_SERVICE_RETRY_COUNT) {
266 mRetryCount++;
267 }
268 return timeout;
269 }
270 };
271
272 public Connector(Context context, int phoneId, Listener listener) {
273 mContext = context;
274 mPhoneId = phoneId;
275 mListener = listener;
276 }
277
278 public Connector(Context context, int phoneId, Listener listener, Looper looper) {
279 super(looper);
280 mContext = context;
281 mPhoneId = phoneId;
282 mListener= listener;
283 }
284
285 /**
286 * Start the creation of a connection to the underlying ImsService implementation. When the
287 * service is connected, {@link Listener#connectionReady(ImsManager)} will be called with
288 * an active ImsManager instance.
289 */
290 public void connect() {
291 mRetryCount = 0;
292 // Send a message to connect to the Ims Service and open a connection through
293 // getImsService().
294 post(mGetServiceRunnable);
295 }
296
297 /**
298 * Disconnect from the ImsService Implementation and clean up. When this is complete,
299 * {@link Listener#connectionUnavailable()} will be called one last time.
300 */
301 public void disconnect() {
302 removeCallbacks(mGetServiceRunnable);
303 synchronized (mLock) {
304 if (mImsManager != null) {
305 mImsManager.removeNotifyStatusChangedCallback(mNotifyStatusChangedCallback);
306 }
307 }
308 notifyNotReady();
309 }
310
311 private void retryGetImsService() {
312 synchronized (mLock) {
313 // remove callback so we do not receive updates from old ImsServiceProxy when
314 // switching between ImsServices.
315 mImsManager.removeNotifyStatusChangedCallback(mNotifyStatusChangedCallback);
316 //Leave mImsManager as null, then CallStateException will be thrown when dialing
317 mImsManager = null;
318 }
319 // Exponential backoff during retry, limited to 32 seconds.
320 loge("Connector: Retrying getting ImsService...");
321 removeCallbacks(mGetServiceRunnable);
322 postDelayed(mGetServiceRunnable, mRetryTimeout.get());
323 }
324
325 private void getImsService() throws ImsException {
326 if (DBG) log("Connector: getImsService");
327 synchronized (mLock) {
328 mImsManager = ImsManager.getInstance(mContext, mPhoneId);
329 // Adding to set, will be safe adding multiple times. If the ImsService is not
330 // active yet, this method will throw an ImsException.
331 mImsManager.addNotifyStatusChangedCallbackIfAvailable(mNotifyStatusChangedCallback);
332 }
333 // Wait for ImsService.STATE_READY to start listening for calls.
334 // Call the callback right away for compatibility with older devices that do not use
335 // states.
336 mNotifyStatusChangedCallback.notifyStateChanged();
337 }
338
339 private void notifyReady() throws ImsException {
340 ImsManager manager;
341 synchronized (mLock) {
342 mRetryCount = 0;
343 manager = mImsManager;
344 }
345 mListener.connectionReady(manager);
346 }
347
348 private void notifyNotReady() {
349 mListener.connectionUnavailable();
350 }
351 }
352
Wink Saville1e5a38a2014-10-23 10:24:46 -0700353 private static HashMap<Integer, ImsManager> sImsManagerInstances =
354 new HashMap<Integer, ImsManager>();
Etan Cohend7727462014-07-12 14:54:10 -0700355
Wink Savilleef36ef62014-06-11 08:39:38 -0700356 private Context mContext;
Brad Ebinger16417b42017-03-07 13:48:50 -0800357 private CarrierConfigManager mConfigManager;
Etan Cohenabbd7882014-09-26 22:35:35 -0700358 private int mPhoneId;
Brad Ebinger16780ff2017-01-26 11:18:21 -0800359 private final boolean mConfigDynamicBind;
Brad Ebinger172977a2018-01-16 09:36:56 -0800360 private @Nullable MmTelFeatureConnection mMmTelFeatureConnection = null;
Wink Savilleef36ef62014-06-11 08:39:38 -0700361 private ImsServiceDeathRecipient mDeathRecipient = new ImsServiceDeathRecipient();
362 // Ut interface for the supplementary service configuration
363 private ImsUt mUt = null;
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -0500364 // Interface to get/set ims config items
365 private ImsConfig mConfig = null;
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -0700366 private boolean mConfigUpdated = false;
Wink Savilleef36ef62014-06-11 08:39:38 -0700367
Pavel Zhamaitsiakf4b90322016-01-26 14:34:09 -0800368 private ImsConfigListener mImsConfigListener;
369
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -0700370 // ECBM interface
371 private ImsEcbm mEcbm = null;
372
Tyler Gunn4d128b62016-04-13 15:44:38 -0700373 private ImsMultiEndpoint mMultiEndpoint = null;
374
Brad Ebinger172977a2018-01-16 09:36:56 -0800375 private Set<MmTelFeatureConnection.IFeatureUpdate> mStatusCallbacks =
376 new CopyOnWriteArraySet<>();
Brad Ebinger16780ff2017-01-26 11:18:21 -0800377
Amit Mahajan24f7b162016-07-21 16:33:53 -0700378 public static final String TRUE = "true";
379 public static final String FALSE = "false";
Jack Yu643ffe42016-07-08 14:25:46 -0700380
Naveen Kalla525c3a22017-02-06 14:46:42 -0800381 // mRecentDisconnectReasons stores the last 16 disconnect reasons
382 private static final int MAX_RECENT_DISCONNECT_REASONS = 16;
383 private ConcurrentLinkedDeque<ImsReasonInfo> mRecentDisconnectReasons =
384 new ConcurrentLinkedDeque<>();
385
Wink Savilleef36ef62014-06-11 08:39:38 -0700386 /**
387 * Gets a manager instance.
388 *
389 * @param context application context for creating the manager object
Etan Cohenabbd7882014-09-26 22:35:35 -0700390 * @param phoneId the phone ID for the IMS Service
391 * @return the manager instance corresponding to the phoneId
Wink Savilleef36ef62014-06-11 08:39:38 -0700392 */
Etan Cohenabbd7882014-09-26 22:35:35 -0700393 public static ImsManager getInstance(Context context, int phoneId) {
Etan Cohend7727462014-07-12 14:54:10 -0700394 synchronized (sImsManagerInstances) {
Naveen Kalla525c3a22017-02-06 14:46:42 -0800395 if (sImsManagerInstances.containsKey(phoneId)) {
Brad Ebingerff097922017-06-19 15:43:08 -0700396 ImsManager m = sImsManagerInstances.get(phoneId);
397 // May be null for some tests
398 if (m != null) {
399 m.connectIfServiceIsAvailable();
400 }
401 return m;
Naveen Kalla525c3a22017-02-06 14:46:42 -0800402 }
Wink Savilleef36ef62014-06-11 08:39:38 -0700403
Etan Cohenabbd7882014-09-26 22:35:35 -0700404 ImsManager mgr = new ImsManager(context, phoneId);
405 sImsManagerInstances.put(phoneId, mgr);
Etan Cohend7727462014-07-12 14:54:10 -0700406
407 return mgr;
408 }
Wink Savilleef36ef62014-06-11 08:39:38 -0700409 }
410
Etan Cohen45b5f312014-08-19 15:55:08 -0700411 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800412 * Returns the user configuration of Enhanced 4G LTE Mode setting.
413 *
414 * @deprecated Doesn't support MSIM devices. Use
Brad Ebinger479f52c2017-08-28 13:19:22 -0700415 * {@link #isEnhanced4gLteModeSettingEnabledByUser()} instead.
Etan Cohen45b5f312014-08-19 15:55:08 -0700416 */
417 public static boolean isEnhanced4gLteModeSettingEnabledByUser(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700418 ImsManager mgr = ImsManager.getInstance(context,
419 SubscriptionManager.getDefaultVoicePhoneId());
420 if (mgr != null) {
421 return mgr.isEnhanced4gLteModeSettingEnabledByUser();
Sungmin Choi2f1af952016-02-01 17:15:35 +0900422 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700423 loge("isEnhanced4gLteModeSettingEnabledByUser: ImsManager null, returning default value.");
424 return false;
Etan Cohen45b5f312014-08-19 15:55:08 -0700425 }
426
427 /**
manabu, shimoda96aee542017-10-06 15:39:36 +0900428 * Returns the user configuration of Enhanced 4G LTE Mode setting for slot. If the option is
429 * not editable ({@link CarrierConfigManager#KEY_EDITABLE_ENHANCED_4G_LTE_BOOL} is false), or
430 * the setting is not initialized, this method will return default value specified by
431 * {@link CarrierConfigManager#KEY_ENHANCED_4G_LTE_ON_BY_DEFAULT_BOOL}.
432 *
433 * Note that even if the setting was set, it may no longer be editable. If this is the case we
434 * return the default value.
Brad Ebinger16417b42017-03-07 13:48:50 -0800435 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700436 public boolean isEnhanced4gLteModeSettingEnabledByUser() {
Malcolm Chen212ca652017-09-28 17:28:45 -0700437 int setting = SubscriptionManager.getIntegerSubscriptionProperty(
438 getSubId(), SubscriptionManager.ENHANCED_4G_MODE_ENABLED,
439 SUB_PROPERTY_NOT_INITIALIZED, mContext);
manabu, shimoda96aee542017-10-06 15:39:36 +0900440 boolean onByDefault = getBooleanCarrierConfig(
441 CarrierConfigManager.KEY_ENHANCED_4G_LTE_ON_BY_DEFAULT_BOOL);
Malcolm Chen212ca652017-09-28 17:28:45 -0700442
manabu, shimoda96aee542017-10-06 15:39:36 +0900443 // If Enhanced 4G LTE Mode is uneditable or not initialized, we use the default value
444 if (!getBooleanCarrierConfig(CarrierConfigManager.KEY_EDITABLE_ENHANCED_4G_LTE_BOOL)
445 || setting == SUB_PROPERTY_NOT_INITIALIZED) {
446 return onByDefault;
447 } else {
448 return (setting == ImsConfig.FeatureValueConstants.ON);
449 }
Brad Ebinger16417b42017-03-07 13:48:50 -0800450 }
451
452 /**
453 * Change persistent Enhanced 4G LTE Mode setting.
454 *
Brad Ebinger479f52c2017-08-28 13:19:22 -0700455 * @deprecated Doesn't support MSIM devices. Use {@link #setEnhanced4gLteModeSetting(boolean)}
Brad Ebinger16417b42017-03-07 13:48:50 -0800456 * instead.
Etan Cohen82f78122014-12-15 10:10:14 -0800457 */
458 public static void setEnhanced4gLteModeSetting(Context context, boolean enabled) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700459 ImsManager mgr = ImsManager.getInstance(context,
460 SubscriptionManager.getDefaultVoicePhoneId());
461 if (mgr != null) {
462 mgr.setEnhanced4gLteModeSetting(enabled);
Etan Cohen82f78122014-12-15 10:10:14 -0800463 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700464 loge("setEnhanced4gLteModeSetting: ImsManager null, value not set.");
Etan Cohen82f78122014-12-15 10:10:14 -0800465 }
466
467 /**
manabu, shimoda96aee542017-10-06 15:39:36 +0900468 * Change persistent Enhanced 4G LTE Mode setting. If the option is not editable
Brad Ebinger16417b42017-03-07 13:48:50 -0800469 * ({@link CarrierConfigManager#KEY_EDITABLE_ENHANCED_4G_LTE_BOOL} is false), this method will
manabu, shimoda96aee542017-10-06 15:39:36 +0900470 * set the setting to the default value specified by
471 * {@link CarrierConfigManager#KEY_ENHANCED_4G_LTE_ON_BY_DEFAULT_BOOL}.
Brad Ebinger16417b42017-03-07 13:48:50 -0800472 *
473 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700474 public void setEnhanced4gLteModeSetting(boolean enabled) {
manabu, shimoda96aee542017-10-06 15:39:36 +0900475 // If editable=false, we must keep default advanced 4G mode.
476 if (!getBooleanCarrierConfig(CarrierConfigManager.KEY_EDITABLE_ENHANCED_4G_LTE_BOOL)) {
477 enabled = getBooleanCarrierConfig(
478 CarrierConfigManager.KEY_ENHANCED_4G_LTE_ON_BY_DEFAULT_BOOL);
479 }
Brad Ebinger16417b42017-03-07 13:48:50 -0800480
Malcolm Chen212ca652017-09-28 17:28:45 -0700481 int prevSetting = SubscriptionManager.getIntegerSubscriptionProperty(
482 getSubId(), SubscriptionManager.ENHANCED_4G_MODE_ENABLED,
483 SUB_PROPERTY_NOT_INITIALIZED, mContext);
Brad Ebinger16417b42017-03-07 13:48:50 -0800484
manabu, shimoda96aee542017-10-06 15:39:36 +0900485 if (prevSetting != (enabled ?
486 ImsConfig.FeatureValueConstants.ON :
487 ImsConfig.FeatureValueConstants.OFF)) {
Malcolm Chen212ca652017-09-28 17:28:45 -0700488 SubscriptionManager.setSubscriptionProperty(getSubId(),
489 SubscriptionManager.ENHANCED_4G_MODE_ENABLED, booleanToPropertyString(enabled));
490 if (isNonTtyOrTtyOnVolteEnabled()) {
491 try {
492 setAdvanced4GMode(enabled);
493 } catch (ImsException ie) {
494 // do nothing
495 }
Brad Ebinger16417b42017-03-07 13:48:50 -0800496 }
497 }
498 }
499
500 /**
Etan Cohen82f78122014-12-15 10:10:14 -0800501 * Indicates whether the call is non-TTY or if TTY - whether TTY on VoLTE is
502 * supported.
Brad Ebinger16417b42017-03-07 13:48:50 -0800503 * @deprecated Does not support MSIM devices. Please use
Brad Ebinger479f52c2017-08-28 13:19:22 -0700504 * {@link #isNonTtyOrTtyOnVolteEnabled()} instead.
Etan Cohen82f78122014-12-15 10:10:14 -0800505 */
506 public static boolean isNonTtyOrTtyOnVolteEnabled(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700507 ImsManager mgr = ImsManager.getInstance(context,
508 SubscriptionManager.getDefaultVoicePhoneId());
509 if (mgr != null) {
510 return mgr.isNonTtyOrTtyOnVolteEnabled();
511 }
512 loge("isNonTtyOrTtyOnVolteEnabled: ImsManager null, returning default value.");
513 return false;
514 }
515
516 /**
517 * Indicates whether the call is non-TTY or if TTY - whether TTY on VoLTE is
518 * supported on a per slot basis.
519 */
520 public boolean isNonTtyOrTtyOnVolteEnabled() {
521 if (getBooleanCarrierConfig(
fionaxu5803ef02016-03-08 11:48:48 -0800522 CarrierConfigManager.KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL)) {
Etan Cohen82f78122014-12-15 10:10:14 -0800523 return true;
524 }
525
Brad Ebinger479f52c2017-08-28 13:19:22 -0700526 TelecomManager tm = (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
Hall Liue511a202017-08-17 15:49:58 -0700527 if (tm == null) {
528 Log.w(TAG, "isNonTtyOrTtyOnVolteEnabled: telecom not available");
529 return true;
530 }
531 return tm.getCurrentTtyMode() == TelecomManager.TTY_MODE_OFF;
Etan Cohen82f78122014-12-15 10:10:14 -0800532 }
533
534 /**
Etan Cohenea2b5832014-10-23 18:50:35 -0700535 * Returns a platform configuration for VoLTE which may override the user setting.
Brad Ebinger16417b42017-03-07 13:48:50 -0800536 * @deprecated Does not support MSIM devices. Please use
Brad Ebinger479f52c2017-08-28 13:19:22 -0700537 * {@link #isVolteEnabledByPlatform()} instead.
Etan Cohen45b5f312014-08-19 15:55:08 -0700538 */
Etan Cohenea2b5832014-10-23 18:50:35 -0700539 public static boolean isVolteEnabledByPlatform(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700540 ImsManager mgr = ImsManager.getInstance(context,
541 SubscriptionManager.getDefaultVoicePhoneId());
542 if (mgr != null) {
543 return mgr.isVolteEnabledByPlatform();
Etan Cohenaf55a402014-09-04 22:34:41 -0700544 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700545 loge("isVolteEnabledByPlatform: ImsManager null, returning default value.");
546 return false;
Etan Cohenb5388a32014-11-26 11:57:47 -0800547 }
548
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700549 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800550 * Returns a platform configuration for VoLTE which may override the user setting on a per Slot
551 * basis.
552 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700553 public boolean isVolteEnabledByPlatform() {
Malcolm Chen18837ff2017-10-25 17:05:41 -0700554 // We first read the per slot value. If doesn't exist, we read the general value. If still
555 // doesn't exist, we use the hardcoded default value.
556 if (SystemProperties.getInt(
557 PROPERTY_DBG_VOLTE_AVAIL_OVERRIDE + Integer.toString(mPhoneId),
558 SYSTEM_PROPERTY_NOT_SET) == 1 ||
559 SystemProperties.getInt(PROPERTY_DBG_VOLTE_AVAIL_OVERRIDE,
560 SYSTEM_PROPERTY_NOT_SET) == 1) {
Brad Ebinger16417b42017-03-07 13:48:50 -0800561 return true;
562 }
563
564 return mContext.getResources().getBoolean(
565 com.android.internal.R.bool.config_device_volte_available)
Malcolm Chen212ca652017-09-28 17:28:45 -0700566 && getBooleanCarrierConfig(CarrierConfigManager.KEY_CARRIER_VOLTE_AVAILABLE_BOOL)
Brad Ebinger479f52c2017-08-28 13:19:22 -0700567 && isGbaValid();
Brad Ebinger16417b42017-03-07 13:48:50 -0800568 }
569
570 /**
571 * Indicates whether VoLTE is provisioned on device.
572 *
573 * @deprecated Does not support MSIM devices. Please use
Brad Ebinger479f52c2017-08-28 13:19:22 -0700574 * {@link #isVolteProvisionedOnDevice()} instead.
Etan Cohenb5388a32014-11-26 11:57:47 -0800575 */
576 public static boolean isVolteProvisionedOnDevice(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700577 ImsManager mgr = ImsManager.getInstance(context,
578 SubscriptionManager.getDefaultVoicePhoneId());
579 if (mgr != null) {
580 return mgr.isVolteProvisionedOnDevice();
Etan Cohenb5388a32014-11-26 11:57:47 -0800581 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700582 loge("isVolteProvisionedOnDevice: ImsManager null, returning default value.");
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700583 return true;
584 }
585
586 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800587 * Indicates whether VoLTE is provisioned on this slot.
588 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700589 public boolean isVolteProvisionedOnDevice() {
590 if (getBooleanCarrierConfig(
Brad Ebinger16417b42017-03-07 13:48:50 -0800591 CarrierConfigManager.KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL)) {
592 return isVolteProvisioned();
593 }
594
595 return true;
596 }
597
598 /**
Meng Wang54fd41a2017-04-12 11:44:47 -0700599 * Indicates whether VoWifi is provisioned on device.
600 *
601 * When CarrierConfig KEY_CARRIER_VOLTE_OVERRIDE_WFC_PROVISIONING_BOOL is true, and VoLTE is not
602 * provisioned on device, this method returns false.
Brad Ebinger16417b42017-03-07 13:48:50 -0800603 *
604 * @deprecated Does not support MSIM devices. Please use
Brad Ebinger479f52c2017-08-28 13:19:22 -0700605 * {@link #isWfcProvisionedOnDevice()} instead.
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700606 */
607 public static boolean isWfcProvisionedOnDevice(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700608 ImsManager mgr = ImsManager.getInstance(context,
609 SubscriptionManager.getDefaultVoicePhoneId());
610 if (mgr != null) {
611 return mgr.isWfcProvisionedOnDevice();
Meng Wang54fd41a2017-04-12 11:44:47 -0700612 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700613 loge("isWfcProvisionedOnDevice: ImsManager null, returning default value.");
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700614 return true;
615 }
616
617 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800618 * Indicates whether VoWifi is provisioned on slot.
Meng Wang54fd41a2017-04-12 11:44:47 -0700619 *
620 * When CarrierConfig KEY_CARRIER_VOLTE_OVERRIDE_WFC_PROVISIONING_BOOL is true, and VoLTE is not
621 * provisioned on device, this method returns false.
Brad Ebinger16417b42017-03-07 13:48:50 -0800622 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700623 public boolean isWfcProvisionedOnDevice() {
624 if (getBooleanCarrierConfig(
Meng Wang54fd41a2017-04-12 11:44:47 -0700625 CarrierConfigManager.KEY_CARRIER_VOLTE_OVERRIDE_WFC_PROVISIONING_BOOL)) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700626 if (!isVolteProvisionedOnDevice()) {
Meng Wang54fd41a2017-04-12 11:44:47 -0700627 return false;
628 }
629 }
630
Brad Ebinger479f52c2017-08-28 13:19:22 -0700631 if (getBooleanCarrierConfig(
Brad Ebinger16417b42017-03-07 13:48:50 -0800632 CarrierConfigManager.KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL)) {
Meng Wang54fd41a2017-04-12 11:44:47 -0700633 return isWfcProvisioned();
Brad Ebinger16417b42017-03-07 13:48:50 -0800634 }
635
636 return true;
637 }
638
639 /**
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700640 * Indicates whether VT is provisioned on device
Brad Ebinger16417b42017-03-07 13:48:50 -0800641 *
642 * @deprecated Does not support MSIM devices. Please use
Brad Ebinger479f52c2017-08-28 13:19:22 -0700643 * {@link #isVtProvisionedOnDevice()} instead.
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700644 */
645 public static boolean isVtProvisionedOnDevice(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700646 ImsManager mgr = ImsManager.getInstance(context,
647 SubscriptionManager.getDefaultVoicePhoneId());
648 if (mgr != null) {
649 return mgr.isVtProvisionedOnDevice();
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700650 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700651 loge("isVtProvisionedOnDevice: ImsManager null, returning default value.");
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700652 return true;
Etan Cohenb651fa52014-10-22 10:51:29 -0700653 }
654
Etan Cohenea2b5832014-10-23 18:50:35 -0700655 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800656 * Indicates whether VT is provisioned on slot.
657 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700658 public boolean isVtProvisionedOnDevice() {
659 if (getBooleanCarrierConfig(
Brad Ebinger16417b42017-03-07 13:48:50 -0800660 CarrierConfigManager.KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL)) {
661 return isVtProvisioned();
662 }
663
664 return true;
665 }
666
667 /**
Etan Cohenea2b5832014-10-23 18:50:35 -0700668 * Returns a platform configuration for VT which may override the user setting.
669 *
670 * Note: VT presumes that VoLTE is enabled (these are configuration settings
671 * which must be done correctly).
Brad Ebinger16417b42017-03-07 13:48:50 -0800672 *
673 * @deprecated Does not support MSIM devices. Please use
Brad Ebinger479f52c2017-08-28 13:19:22 -0700674 * {@link #isVtEnabledByPlatform()} instead.
Etan Cohenea2b5832014-10-23 18:50:35 -0700675 */
Etan Cohenb651fa52014-10-22 10:51:29 -0700676 public static boolean isVtEnabledByPlatform(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700677 ImsManager mgr = ImsManager.getInstance(context,
678 SubscriptionManager.getDefaultVoicePhoneId());
679 if (mgr != null) {
680 return mgr.isVtEnabledByPlatform();
Etan Cohenea2b5832014-10-23 18:50:35 -0700681 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700682 loge("isVtEnabledByPlatform: ImsManager null, returning default value.");
683 return false;
Etan Cohen45b5f312014-08-19 15:55:08 -0700684 }
685
Etan Cohena00c9192014-12-23 15:02:29 -0800686 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800687 * Returns a platform configuration for VT which may override the user setting.
688 *
689 * Note: VT presumes that VoLTE is enabled (these are configuration settings
690 * which must be done correctly).
691 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700692 public boolean isVtEnabledByPlatform() {
Malcolm Chen18837ff2017-10-25 17:05:41 -0700693 // We first read the per slot value. If doesn't exist, we read the general value. If still
694 // doesn't exist, we use the hardcoded default value.
695 if (SystemProperties.getInt(PROPERTY_DBG_VT_AVAIL_OVERRIDE +
696 Integer.toString(mPhoneId), SYSTEM_PROPERTY_NOT_SET) == 1 ||
697 SystemProperties.getInt(
698 PROPERTY_DBG_VT_AVAIL_OVERRIDE, SYSTEM_PROPERTY_NOT_SET) == 1) {
Brad Ebinger16417b42017-03-07 13:48:50 -0800699 return true;
700 }
701
702 return mContext.getResources().getBoolean(
703 com.android.internal.R.bool.config_device_vt_available) &&
Malcolm Chen212ca652017-09-28 17:28:45 -0700704 getBooleanCarrierConfig(CarrierConfigManager.KEY_CARRIER_VT_AVAILABLE_BOOL) &&
Brad Ebinger479f52c2017-08-28 13:19:22 -0700705 isGbaValid();
Brad Ebinger16417b42017-03-07 13:48:50 -0800706 }
707
708 /**
Etan Cohena7d32e82015-05-04 18:02:09 -0700709 * Returns the user configuration of VT setting
Brad Ebinger16417b42017-03-07 13:48:50 -0800710 * @deprecated Does not support MSIM devices. Please use
Brad Ebinger479f52c2017-08-28 13:19:22 -0700711 * {@link #isVtEnabledByUser()} instead.
Etan Cohena7d32e82015-05-04 18:02:09 -0700712 */
713 public static boolean isVtEnabledByUser(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700714 ImsManager mgr = ImsManager.getInstance(context,
715 SubscriptionManager.getDefaultVoicePhoneId());
716 if (mgr != null) {
717 return mgr.isVtEnabledByUser();
718 }
719 loge("isVtEnabledByUser: ImsManager null, returning default value.");
720 return false;
Etan Cohena7d32e82015-05-04 18:02:09 -0700721 }
722
723 /**
Malcolm Chen212ca652017-09-28 17:28:45 -0700724 * Returns the user configuration of VT setting per slot. If not set, it
725 * returns true as default value.
Brad Ebinger16417b42017-03-07 13:48:50 -0800726 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700727 public boolean isVtEnabledByUser() {
Malcolm Chen212ca652017-09-28 17:28:45 -0700728 int setting = SubscriptionManager.getIntegerSubscriptionProperty(
729 getSubId(), SubscriptionManager.VT_IMS_ENABLED,
730 SUB_PROPERTY_NOT_INITIALIZED, mContext);
731
732 // If it's never set, by default we return true.
manabu, shimoda96aee542017-10-06 15:39:36 +0900733 return (setting == SUB_PROPERTY_NOT_INITIALIZED
734 || setting == ImsConfig.FeatureValueConstants.ON);
Brad Ebinger16417b42017-03-07 13:48:50 -0800735 }
736
737 /**
Etan Cohena7d32e82015-05-04 18:02:09 -0700738 * Change persistent VT enabled setting
Brad Ebinger16417b42017-03-07 13:48:50 -0800739 *
Brad Ebinger479f52c2017-08-28 13:19:22 -0700740 * @deprecated Does not support MSIM devices. Please use {@link #setVtSetting(boolean)} instead.
Etan Cohena7d32e82015-05-04 18:02:09 -0700741 */
742 public static void setVtSetting(Context context, boolean enabled) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700743 ImsManager mgr = ImsManager.getInstance(context,
Etan Cohena7d32e82015-05-04 18:02:09 -0700744 SubscriptionManager.getDefaultVoicePhoneId());
Brad Ebinger479f52c2017-08-28 13:19:22 -0700745 if (mgr != null) {
746 mgr.setVtSetting(enabled);
Etan Cohena7d32e82015-05-04 18:02:09 -0700747 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700748 loge("setVtSetting: ImsManager null, can not set value.");
Etan Cohena7d32e82015-05-04 18:02:09 -0700749 }
750
Brad Ebinger16417b42017-03-07 13:48:50 -0800751 /**
752 * Change persistent VT enabled setting for slot.
753 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700754 public void setVtSetting(boolean enabled) {
Brad Ebinger172977a2018-01-16 09:36:56 -0800755 SubscriptionManager.setSubscriptionProperty(getSubId(), SubscriptionManager.VT_IMS_ENABLED,
Malcolm Chen212ca652017-09-28 17:28:45 -0700756 booleanToPropertyString(enabled));
Brad Ebinger172977a2018-01-16 09:36:56 -0800757
Brad Ebinger16417b42017-03-07 13:48:50 -0800758 try {
Brad Ebinger172977a2018-01-16 09:36:56 -0800759 changeMmTelCapability(MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VIDEO,
760 ImsRegistrationImplBase.REGISTRATION_TECH_LTE, enabled);
Brad Ebinger16417b42017-03-07 13:48:50 -0800761
762 if (enabled) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700763 log("setVtSetting(b) : turnOnIms");
Brad Ebinger16417b42017-03-07 13:48:50 -0800764 turnOnIms();
Brad Ebinger479f52c2017-08-28 13:19:22 -0700765 } else if (isVolteEnabledByPlatform()
766 && (!isVolteEnabledByPlatform()
767 || !isEnhanced4gLteModeSettingEnabledByUser())) {
768 log("setVtSetting(b) : imsServiceAllowTurnOff -> turnOffIms");
Brad Ebinger16417b42017-03-07 13:48:50 -0800769 turnOffIms();
770 }
Brad Ebinger172977a2018-01-16 09:36:56 -0800771 } catch (ImsException | RemoteException e) {
772 // The ImsService is down. Since the SubscriptionManager already recorded the user's
773 // preference, it will be resent in updateImsServiceConfig when the ImsPhoneCallTracker
774 // reconnects.
Brad Ebinger479f52c2017-08-28 13:19:22 -0700775 loge("setVtSetting(b): ", e);
Brad Ebinger16417b42017-03-07 13:48:50 -0800776 }
777 }
778
779 /**
Meng Wang9352c432016-06-08 14:22:20 -0700780 * Returns whether turning off ims is allowed by platform.
781 * The platform property may override the carrier config.
Brad Ebinger16417b42017-03-07 13:48:50 -0800782 *
783 * @deprecated Does not support MSIM devices. Please use
Brad Ebinger479f52c2017-08-28 13:19:22 -0700784 * {@link #isTurnOffImsAllowedByPlatform()} instead.
Meng Wang9352c432016-06-08 14:22:20 -0700785 */
786 private static boolean isTurnOffImsAllowedByPlatform(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700787 ImsManager mgr = ImsManager.getInstance(context,
788 SubscriptionManager.getDefaultVoicePhoneId());
789 if (mgr != null) {
790 return mgr.isTurnOffImsAllowedByPlatform();
Meng Wang9352c432016-06-08 14:22:20 -0700791 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700792 loge("isTurnOffImsAllowedByPlatform: ImsManager null, returning default value.");
793 return true;
Meng Wang9352c432016-06-08 14:22:20 -0700794 }
795
Etan Cohena7d32e82015-05-04 18:02:09 -0700796 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800797 * Returns whether turning off ims is allowed by platform.
798 * The platform property may override the carrier config.
799 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700800 private boolean isTurnOffImsAllowedByPlatform() {
Malcolm Chen18837ff2017-10-25 17:05:41 -0700801 // We first read the per slot value. If doesn't exist, we read the general value. If still
802 // doesn't exist, we use the hardcoded default value.
803 if (SystemProperties.getInt(PROPERTY_DBG_ALLOW_IMS_OFF_OVERRIDE +
804 Integer.toString(mPhoneId), SYSTEM_PROPERTY_NOT_SET) == 1 ||
805 SystemProperties.getInt(
806 PROPERTY_DBG_ALLOW_IMS_OFF_OVERRIDE, SYSTEM_PROPERTY_NOT_SET) == 1) {
Brad Ebinger16417b42017-03-07 13:48:50 -0800807 return true;
808 }
Malcolm Chen18837ff2017-10-25 17:05:41 -0700809
Brad Ebinger479f52c2017-08-28 13:19:22 -0700810 return getBooleanCarrierConfig(
Brad Ebinger16417b42017-03-07 13:48:50 -0800811 CarrierConfigManager.KEY_CARRIER_ALLOW_TURNOFF_IMS_BOOL);
812 }
813
814 /**
Etan Cohena00c9192014-12-23 15:02:29 -0800815 * Returns the user configuration of WFC setting
Brad Ebinger16417b42017-03-07 13:48:50 -0800816 *
817 * @deprecated Does not support MSIM devices. Please use
Brad Ebinger479f52c2017-08-28 13:19:22 -0700818 * {@link #isWfcEnabledByUser()} instead.
Etan Cohena00c9192014-12-23 15:02:29 -0800819 */
820 public static boolean isWfcEnabledByUser(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700821 ImsManager mgr = ImsManager.getInstance(context,
822 SubscriptionManager.getDefaultVoicePhoneId());
823 if (mgr != null) {
824 return mgr.isWfcEnabledByUser();
825 }
826 loge("isWfcEnabledByUser: ImsManager null, returning default value.");
827 return true;
Etan Cohena00c9192014-12-23 15:02:29 -0800828 }
829
830 /**
Malcolm Chen212ca652017-09-28 17:28:45 -0700831 * Returns the user configuration of WFC setting for slot. If not set, it
832 * queries CarrierConfig value as default.
Brad Ebinger16417b42017-03-07 13:48:50 -0800833 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700834 public boolean isWfcEnabledByUser() {
Malcolm Chen212ca652017-09-28 17:28:45 -0700835 int setting = SubscriptionManager.getIntegerSubscriptionProperty(
836 getSubId(), SubscriptionManager.WFC_IMS_ENABLED,
837 SUB_PROPERTY_NOT_INITIALIZED, mContext);
838
839 // SUB_PROPERTY_NOT_INITIALIZED indicates it's never set in sub db.
840 if (setting == SUB_PROPERTY_NOT_INITIALIZED) {
841 return getBooleanCarrierConfig(
842 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ENABLED_BOOL);
843 } else {
manabu, shimoda96aee542017-10-06 15:39:36 +0900844 return setting == ImsConfig.FeatureValueConstants.ON;
Malcolm Chen212ca652017-09-28 17:28:45 -0700845 }
Brad Ebinger16417b42017-03-07 13:48:50 -0800846 }
847
848 /**
849 * Change persistent WFC enabled setting.
850 * @deprecated Does not support MSIM devices. Please use
Brad Ebinger479f52c2017-08-28 13:19:22 -0700851 * {@link #setWfcSetting} instead.
Etan Cohena00c9192014-12-23 15:02:29 -0800852 */
853 public static void setWfcSetting(Context context, boolean enabled) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700854 ImsManager mgr = ImsManager.getInstance(context,
Etan Cohena00c9192014-12-23 15:02:29 -0800855 SubscriptionManager.getDefaultVoicePhoneId());
Brad Ebinger479f52c2017-08-28 13:19:22 -0700856 if (mgr != null) {
857 mgr.setWfcSetting(enabled);
Etan Cohena00c9192014-12-23 15:02:29 -0800858 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700859 loge("setWfcSetting: ImsManager null, can not set value.");
Etan Cohena00c9192014-12-23 15:02:29 -0800860 }
861
862 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800863 * Change persistent WFC enabled setting for slot.
864 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700865 public void setWfcSetting(boolean enabled) {
Malcolm Chen212ca652017-09-28 17:28:45 -0700866 SubscriptionManager.setSubscriptionProperty(getSubId(),
867 SubscriptionManager.WFC_IMS_ENABLED, booleanToPropertyString(enabled));
Brad Ebinger16417b42017-03-07 13:48:50 -0800868
Brad Ebinger479f52c2017-08-28 13:19:22 -0700869 setWfcNonPersistent(enabled, getWfcMode());
Meng Wang51c09072017-03-27 10:47:45 -0700870 }
871
872 /**
873 * Non-persistently change WFC enabled setting and WFC mode for slot
874 *
875 * @param wfcMode The WFC preference if WFC is enabled
876 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700877 public void setWfcNonPersistent(boolean enabled, int wfcMode) {
Meng Wang51c09072017-03-27 10:47:45 -0700878 // Force IMS to register over LTE when turning off WFC
879 int imsWfcModeFeatureValue =
880 enabled ? wfcMode : ImsConfig.WfcModeFeatureValueConstants.CELLULAR_PREFERRED;
881
Brad Ebinger16417b42017-03-07 13:48:50 -0800882 try {
Brad Ebinger172977a2018-01-16 09:36:56 -0800883 changeMmTelCapability(MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE,
884 ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN, enabled);
Brad Ebinger16417b42017-03-07 13:48:50 -0800885
886 if (enabled) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700887 log("setWfcSetting() : turnOnIms");
Brad Ebinger16417b42017-03-07 13:48:50 -0800888 turnOnIms();
Brad Ebinger479f52c2017-08-28 13:19:22 -0700889 } else if (isTurnOffImsAllowedByPlatform()
890 && (!isVolteEnabledByPlatform()
891 || !isEnhanced4gLteModeSettingEnabledByUser())) {
892 log("setWfcSetting() : imsServiceAllowTurnOff -> turnOffIms");
Brad Ebinger16417b42017-03-07 13:48:50 -0800893 turnOffIms();
894 }
895
Brad Ebinger479f52c2017-08-28 13:19:22 -0700896 setWfcModeInternal(imsWfcModeFeatureValue);
Brad Ebinger172977a2018-01-16 09:36:56 -0800897 } catch (ImsException | RemoteException e) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700898 loge("setWfcSetting(): ", e);
Brad Ebinger16417b42017-03-07 13:48:50 -0800899 }
900 }
901
902 /**
903 * Returns the user configuration of WFC preference setting.
904 *
Malcolm Chen212ca652017-09-28 17:28:45 -0700905 * @deprecated Doesn't support MSIM devices. Use {@link #getWfcMode(boolean roaming)} instead.
Etan Cohena00c9192014-12-23 15:02:29 -0800906 */
907 public static int getWfcMode(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700908 ImsManager mgr = ImsManager.getInstance(context,
909 SubscriptionManager.getDefaultVoicePhoneId());
910 if (mgr != null) {
911 return mgr.getWfcMode();
912 }
913 loge("getWfcMode: ImsManager null, returning default value.");
914 return ImsConfig.WfcModeFeatureValueConstants.WIFI_ONLY;
Etan Cohena00c9192014-12-23 15:02:29 -0800915 }
916
917 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800918 * Returns the user configuration of WFC preference setting
Malcolm Chen212ca652017-09-28 17:28:45 -0700919 * @deprecated. Use {@link #getWfcMode(boolean roaming)} instead.
Brad Ebinger16417b42017-03-07 13:48:50 -0800920 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700921 public int getWfcMode() {
Malcolm Chen212ca652017-09-28 17:28:45 -0700922 return getWfcMode(false);
Brad Ebinger16417b42017-03-07 13:48:50 -0800923 }
924
925 /**
926 * Change persistent WFC preference setting.
927 *
Brad Ebinger479f52c2017-08-28 13:19:22 -0700928 * @deprecated Doesn't support MSIM devices. Use {@link #setWfcMode(int)} instead.
Etan Cohena00c9192014-12-23 15:02:29 -0800929 */
930 public static void setWfcMode(Context context, int wfcMode) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700931 ImsManager mgr = ImsManager.getInstance(context,
932 SubscriptionManager.getDefaultVoicePhoneId());
933 if (mgr != null) {
934 mgr.setWfcMode(wfcMode);
935 }
936 loge("setWfcMode: ImsManager null, can not set value.");
Pavel Zhamaitsiak9e6eca22015-03-16 15:30:53 -0700937 }
938
Meng Wang37477012016-09-20 09:59:56 -0700939 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800940 * Change persistent WFC preference setting for slot.
941 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700942 public void setWfcMode(int wfcMode) {
943 if (DBG) log("setWfcMode(i) - setting=" + wfcMode);
Malcolm Chen212ca652017-09-28 17:28:45 -0700944
945 SubscriptionManager.setSubscriptionProperty(getSubId(),
946 SubscriptionManager.WFC_IMS_MODE, Integer.toString(wfcMode));
Brad Ebinger16417b42017-03-07 13:48:50 -0800947
Brad Ebinger479f52c2017-08-28 13:19:22 -0700948 setWfcModeInternal(wfcMode);
Brad Ebinger16417b42017-03-07 13:48:50 -0800949 }
950
951 /**
Suresh Koleti76491082017-04-21 18:39:50 +0530952 * Changes the WFC mode to its default value for Carriers with non-editable WFC settings.
953 */
954 private void updateDefaultWfcMode() {
955 if (DBG) log("updateDefaultWfcMode");
Brad Ebinger479f52c2017-08-28 13:19:22 -0700956 if (!getBooleanCarrierConfig(CarrierConfigManager.KEY_EDITABLE_WFC_MODE_BOOL)) {
957 setWfcMode(getIntCarrierConfig(
Suresh Koleti76491082017-04-21 18:39:50 +0530958 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_MODE_INT));
959 }
960 }
961
962 /**
Meng Wang37477012016-09-20 09:59:56 -0700963 * Returns the user configuration of WFC preference setting
964 *
965 * @param roaming {@code false} for home network setting, {@code true} for roaming setting
Brad Ebinger16417b42017-03-07 13:48:50 -0800966 *
Brad Ebinger479f52c2017-08-28 13:19:22 -0700967 * @deprecated Doesn't support MSIM devices. Use {@link #getWfcMode(boolean)} instead.
Meng Wang37477012016-09-20 09:59:56 -0700968 */
969 public static int getWfcMode(Context context, boolean roaming) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700970 ImsManager mgr = ImsManager.getInstance(context,
971 SubscriptionManager.getDefaultVoicePhoneId());
972 if (mgr != null) {
973 return mgr.getWfcMode(roaming);
Meng Wang37477012016-09-20 09:59:56 -0700974 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700975 loge("getWfcMode: ImsManager null, returning default value.");
976 return ImsConfig.WfcModeFeatureValueConstants.WIFI_ONLY;
Meng Wang37477012016-09-20 09:59:56 -0700977 }
978
979 /**
Malcolm Chen212ca652017-09-28 17:28:45 -0700980 * Returns the user configuration of WFC preference setting for slot. If not set, it
981 * queries CarrierConfig value as default.
Brad Ebinger16417b42017-03-07 13:48:50 -0800982 *
983 * @param roaming {@code false} for home network setting, {@code true} for roaming setting
984 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700985 public int getWfcMode(boolean roaming) {
Brad Ebinger16417b42017-03-07 13:48:50 -0800986 int setting = 0;
987 if (!roaming) {
Malcolm Chen212ca652017-09-28 17:28:45 -0700988 setting = SubscriptionManager.getIntegerSubscriptionProperty(
989 getSubId(), SubscriptionManager.WFC_IMS_MODE,
990 SUB_PROPERTY_NOT_INITIALIZED, mContext);
991
992 // SUB_PROPERTY_NOT_INITIALIZED indicates it's never set in sub db.
993 if (setting == SUB_PROPERTY_NOT_INITIALIZED) {
994 setting = getIntCarrierConfig(
995 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_MODE_INT);
996 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700997 if (DBG) log("getWfcMode - setting=" + setting);
Brad Ebinger16417b42017-03-07 13:48:50 -0800998 } else {
Malcolm Chen212ca652017-09-28 17:28:45 -0700999 setting = SubscriptionManager.getIntegerSubscriptionProperty(
1000 getSubId(), SubscriptionManager.WFC_IMS_ROAMING_MODE,
1001 SUB_PROPERTY_NOT_INITIALIZED, mContext);
1002
1003 // SUB_PROPERTY_NOT_INITIALIZED indicates it's never set in sub db.
1004 if (setting == SUB_PROPERTY_NOT_INITIALIZED) {
1005 setting = getIntCarrierConfig(
1006 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_MODE_INT);
1007 }
1008
Brad Ebinger479f52c2017-08-28 13:19:22 -07001009 if (DBG) log("getWfcMode (roaming) - setting=" + setting);
Brad Ebinger16417b42017-03-07 13:48:50 -08001010 }
1011 return setting;
1012 }
1013
1014 /**
Meng Wang37477012016-09-20 09:59:56 -07001015 * Change persistent WFC preference setting
1016 *
1017 * @param roaming {@code false} for home network setting, {@code true} for roaming setting
Brad Ebinger16417b42017-03-07 13:48:50 -08001018 *
Brad Ebinger479f52c2017-08-28 13:19:22 -07001019 * @deprecated Doesn't support MSIM devices. Please use {@link #setWfcMode(int, boolean)}
1020 * instead.
Meng Wang37477012016-09-20 09:59:56 -07001021 */
1022 public static void setWfcMode(Context context, int wfcMode, boolean roaming) {
Brad Ebinger479f52c2017-08-28 13:19:22 -07001023 ImsManager mgr = ImsManager.getInstance(context,
1024 SubscriptionManager.getDefaultVoicePhoneId());
1025 if (mgr != null) {
1026 mgr.setWfcMode(wfcMode, roaming);
Meng Wang37477012016-09-20 09:59:56 -07001027 }
Brad Ebinger479f52c2017-08-28 13:19:22 -07001028 loge("setWfcMode: ImsManager null, can not set value.");
Meng Wang37477012016-09-20 09:59:56 -07001029 }
1030
Brad Ebinger16417b42017-03-07 13:48:50 -08001031 /**
1032 * Change persistent WFC preference setting
1033 *
1034 * @param roaming {@code false} for home network setting, {@code true} for roaming setting
1035 */
Brad Ebinger479f52c2017-08-28 13:19:22 -07001036 public void setWfcMode(int wfcMode, boolean roaming) {
Brad Ebinger16417b42017-03-07 13:48:50 -08001037 if (!roaming) {
Brad Ebinger479f52c2017-08-28 13:19:22 -07001038 if (DBG) log("setWfcMode(i,b) - setting=" + wfcMode);
Malcolm Chen212ca652017-09-28 17:28:45 -07001039 SubscriptionManager.setSubscriptionProperty(getSubId(),
1040 SubscriptionManager.WFC_IMS_MODE, Integer.toString(wfcMode));
Brad Ebinger16417b42017-03-07 13:48:50 -08001041 } else {
Brad Ebinger479f52c2017-08-28 13:19:22 -07001042 if (DBG) log("setWfcMode(i,b) (roaming) - setting=" + wfcMode);
Malcolm Chen212ca652017-09-28 17:28:45 -07001043 SubscriptionManager.setSubscriptionProperty(getSubId(),
1044 SubscriptionManager.WFC_IMS_ROAMING_MODE, Integer.toString(wfcMode));
Brad Ebinger16417b42017-03-07 13:48:50 -08001045 }
1046
Brad Ebinger479f52c2017-08-28 13:19:22 -07001047 TelephonyManager tm = (TelephonyManager)
1048 mContext.getSystemService(Context.TELEPHONY_SERVICE);
1049 if (roaming == tm.isNetworkRoaming(getSubId())) {
1050 setWfcModeInternal(wfcMode);
1051 }
1052 }
1053
1054 private int getSubId() {
Brad Ebinger16417b42017-03-07 13:48:50 -08001055 int[] subIds = SubscriptionManager.getSubId(mPhoneId);
1056 int subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1057 if (subIds != null && subIds.length >= 1) {
1058 subId = subIds[0];
1059 }
Brad Ebinger479f52c2017-08-28 13:19:22 -07001060 return subId;
Brad Ebinger16417b42017-03-07 13:48:50 -08001061 }
1062
Pavel Zhamaitsiak9e6eca22015-03-16 15:30:53 -07001063 private static void setWfcModeInternal(Context context, int wfcMode) {
Etan Cohena00c9192014-12-23 15:02:29 -08001064 final ImsManager imsManager = ImsManager.getInstance(context,
1065 SubscriptionManager.getDefaultVoicePhoneId());
1066 if (imsManager != null) {
1067 final int value = wfcMode;
Pavel Zhamaitsiak47aeacf2016-03-30 18:54:55 -07001068 Thread thread = new Thread(new Runnable() {
Etan Cohena00c9192014-12-23 15:02:29 -08001069 public void run() {
1070 try {
Brad Ebinger172977a2018-01-16 09:36:56 -08001071 imsManager.getConfigInterface().setConfig(
Etan Cohena00c9192014-12-23 15:02:29 -08001072 ImsConfig.ConfigConstants.VOICE_OVER_WIFI_MODE,
1073 value);
1074 } catch (ImsException e) {
1075 // do nothing
1076 }
1077 }
1078 });
Pavel Zhamaitsiak47aeacf2016-03-30 18:54:55 -07001079 thread.start();
Etan Cohena00c9192014-12-23 15:02:29 -08001080 }
1081 }
1082
Brad Ebinger479f52c2017-08-28 13:19:22 -07001083 private void setWfcModeInternal(int wfcMode) {
Brad Ebinger16417b42017-03-07 13:48:50 -08001084 final int value = wfcMode;
1085 Thread thread = new Thread(() -> {
Malcolm Chen212ca652017-09-28 17:28:45 -07001086 try {
Brad Ebinger172977a2018-01-16 09:36:56 -08001087 getConfigInterface().setConfig(
Malcolm Chen212ca652017-09-28 17:28:45 -07001088 ImsConfig.ConfigConstants.VOICE_OVER_WIFI_MODE, value);
1089 } catch (ImsException e) {
1090 // do nothing
1091 }
Brad Ebinger16417b42017-03-07 13:48:50 -08001092 });
1093 thread.start();
1094 }
1095
Etan Cohena00c9192014-12-23 15:02:29 -08001096 /**
1097 * Returns the user configuration of WFC roaming setting
Brad Ebinger16417b42017-03-07 13:48:50 -08001098 *
1099 * @deprecated Does not support MSIM devices. Please use
Brad Ebinger479f52c2017-08-28 13:19:22 -07001100 * {@link #isWfcRoamingEnabledByUser()} instead.
Etan Cohena00c9192014-12-23 15:02:29 -08001101 */
1102 public static boolean isWfcRoamingEnabledByUser(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -07001103 ImsManager mgr = ImsManager.getInstance(context,
1104 SubscriptionManager.getDefaultVoicePhoneId());
1105 if (mgr != null) {
1106 return mgr.isWfcRoamingEnabledByUser();
1107 }
1108 loge("isWfcRoamingEnabledByUser: ImsManager null, returning default value.");
1109 return false;
Etan Cohena00c9192014-12-23 15:02:29 -08001110 }
1111
1112 /**
Malcolm Chen212ca652017-09-28 17:28:45 -07001113 * Returns the user configuration of WFC roaming setting for slot. If not set, it
1114 * queries CarrierConfig value as default.
Brad Ebinger16417b42017-03-07 13:48:50 -08001115 */
Brad Ebinger479f52c2017-08-28 13:19:22 -07001116 public boolean isWfcRoamingEnabledByUser() {
Malcolm Chen212ca652017-09-28 17:28:45 -07001117 int setting = SubscriptionManager.getIntegerSubscriptionProperty(
1118 getSubId(), SubscriptionManager.WFC_IMS_ROAMING_ENABLED,
1119 SUB_PROPERTY_NOT_INITIALIZED, mContext);
1120 if (setting == SUB_PROPERTY_NOT_INITIALIZED) {
1121 return getBooleanCarrierConfig(
1122 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_ENABLED_BOOL);
1123 } else {
manabu, shimoda96aee542017-10-06 15:39:36 +09001124 return setting == ImsConfig.FeatureValueConstants.ON;
Malcolm Chen212ca652017-09-28 17:28:45 -07001125 }
Brad Ebinger16417b42017-03-07 13:48:50 -08001126 }
1127
1128 /**
Etan Cohena00c9192014-12-23 15:02:29 -08001129 * Change persistent WFC roaming enabled setting
1130 */
1131 public static void setWfcRoamingSetting(Context context, boolean enabled) {
Brad Ebinger479f52c2017-08-28 13:19:22 -07001132 ImsManager mgr = ImsManager.getInstance(context,
Etan Cohena00c9192014-12-23 15:02:29 -08001133 SubscriptionManager.getDefaultVoicePhoneId());
Brad Ebinger479f52c2017-08-28 13:19:22 -07001134 if (mgr != null) {
1135 mgr.setWfcRoamingSetting(enabled);
Etan Cohena00c9192014-12-23 15:02:29 -08001136 }
Brad Ebinger479f52c2017-08-28 13:19:22 -07001137 loge("setWfcRoamingSetting: ImsManager null, value not set.");
Etan Cohena00c9192014-12-23 15:02:29 -08001138 }
1139
1140 /**
Brad Ebinger16417b42017-03-07 13:48:50 -08001141 * Change persistent WFC roaming enabled setting
1142 */
Brad Ebinger479f52c2017-08-28 13:19:22 -07001143 public void setWfcRoamingSetting(boolean enabled) {
Malcolm Chen212ca652017-09-28 17:28:45 -07001144 SubscriptionManager.setSubscriptionProperty(getSubId(),
1145 SubscriptionManager.WFC_IMS_ROAMING_ENABLED, booleanToPropertyString(enabled)
1146 );
Brad Ebinger16417b42017-03-07 13:48:50 -08001147
1148 setWfcRoamingSettingInternal(enabled);
1149 }
1150
1151 private void setWfcRoamingSettingInternal(boolean enabled) {
1152 final int value = enabled
1153 ? ImsConfig.FeatureValueConstants.ON
1154 : ImsConfig.FeatureValueConstants.OFF;
1155 Thread thread = new Thread(() -> {
Malcolm Chen212ca652017-09-28 17:28:45 -07001156 try {
Brad Ebinger172977a2018-01-16 09:36:56 -08001157 getConfigInterface().setConfig(
Malcolm Chen212ca652017-09-28 17:28:45 -07001158 ImsConfig.ConfigConstants.VOICE_OVER_WIFI_ROAMING, value);
1159 } catch (ImsException e) {
1160 // do nothing
1161 }
Brad Ebinger16417b42017-03-07 13:48:50 -08001162 });
1163 thread.start();
1164 }
1165
1166 /**
Etan Cohena00c9192014-12-23 15:02:29 -08001167 * Returns a platform configuration for WFC which may override the user
1168 * setting. Note: WFC presumes that VoLTE is enabled (these are
1169 * configuration settings which must be done correctly).
Brad Ebinger16417b42017-03-07 13:48:50 -08001170 *
Brad Ebinger479f52c2017-08-28 13:19:22 -07001171 * @deprecated Doesn't work for MSIM devices. Use {@link #isWfcEnabledByPlatform()}
Brad Ebinger16417b42017-03-07 13:48:50 -08001172 * instead.
Etan Cohena00c9192014-12-23 15:02:29 -08001173 */
1174 public static boolean isWfcEnabledByPlatform(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -07001175 ImsManager mgr = ImsManager.getInstance(context,
1176 SubscriptionManager.getDefaultVoicePhoneId());
1177 if (mgr != null) {
1178 return mgr.isWfcEnabledByPlatform();
Etan Cohena00c9192014-12-23 15:02:29 -08001179 }
Brad Ebinger479f52c2017-08-28 13:19:22 -07001180 loge("isWfcEnabledByPlatform: ImsManager null, returning default value.");
1181 return false;
Pavel Zhamaitsiak57911d12015-10-20 14:26:34 -07001182 }
1183
1184 /**
Brad Ebinger16417b42017-03-07 13:48:50 -08001185 * Returns a platform configuration for WFC which may override the user
1186 * setting per slot. Note: WFC presumes that VoLTE is enabled (these are
1187 * configuration settings which must be done correctly).
1188 */
Brad Ebinger479f52c2017-08-28 13:19:22 -07001189 public boolean isWfcEnabledByPlatform() {
Malcolm Chen18837ff2017-10-25 17:05:41 -07001190 // We first read the per slot value. If doesn't exist, we read the general value. If still
1191 // doesn't exist, we use the hardcoded default value.
1192 if (SystemProperties.getInt(PROPERTY_DBG_WFC_AVAIL_OVERRIDE +
1193 Integer.toString(mPhoneId), SYSTEM_PROPERTY_NOT_SET) == 1 ||
1194 SystemProperties.getInt(
1195 PROPERTY_DBG_WFC_AVAIL_OVERRIDE, SYSTEM_PROPERTY_NOT_SET) == 1) {
Brad Ebinger16417b42017-03-07 13:48:50 -08001196 return true;
1197 }
1198
1199 return mContext.getResources().getBoolean(
1200 com.android.internal.R.bool.config_device_wfc_ims_available) &&
Brad Ebinger479f52c2017-08-28 13:19:22 -07001201 getBooleanCarrierConfig(
Brad Ebinger16417b42017-03-07 13:48:50 -08001202 CarrierConfigManager.KEY_CARRIER_WFC_IMS_AVAILABLE_BOOL) &&
Brad Ebinger479f52c2017-08-28 13:19:22 -07001203 isGbaValid();
Etan Cohena00c9192014-12-23 15:02:29 -08001204 }
1205
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001206 /**
Brad Ebinger16417b42017-03-07 13:48:50 -08001207 * If carrier requires that IMS is only available if GBA capable SIM is used,
1208 * then this function checks GBA bit in EF IST.
1209 *
1210 * Format of EF IST is defined in 3GPP TS 31.103 (Section 4.2.7).
1211 */
Brad Ebinger479f52c2017-08-28 13:19:22 -07001212 private boolean isGbaValid() {
1213 if (getBooleanCarrierConfig(
Brad Ebinger16417b42017-03-07 13:48:50 -08001214 CarrierConfigManager.KEY_CARRIER_IMS_GBA_REQUIRED_BOOL)) {
Brad Ebinger479f52c2017-08-28 13:19:22 -07001215 final TelephonyManager telephonyManager = new TelephonyManager(mContext, getSubId());
Brad Ebinger16417b42017-03-07 13:48:50 -08001216 String efIst = telephonyManager.getIsimIst();
1217 if (efIst == null) {
Brad Ebinger479f52c2017-08-28 13:19:22 -07001218 loge("isGbaValid - ISF is NULL");
Brad Ebinger16417b42017-03-07 13:48:50 -08001219 return true;
1220 }
1221 boolean result = efIst != null && efIst.length() > 1 &&
1222 (0x02 & (byte)efIst.charAt(1)) != 0;
Brad Ebinger479f52c2017-08-28 13:19:22 -07001223 if (DBG) log("isGbaValid - GBA capable=" + result + ", ISF=" + efIst);
Brad Ebinger16417b42017-03-07 13:48:50 -08001224 return result;
1225 }
1226 return true;
1227 }
1228
1229 /**
Malcolm Chen18837ff2017-10-25 17:05:41 -07001230 * Will return with config value or throw an ImsException if we receive an error from
1231 * ImsConfig for that value.
1232 */
1233 private boolean getProvisionedBool(ImsConfig config, int item) throws ImsException {
1234 int value = config.getProvisionedValue(item);
1235 if (value == ImsConfig.OperationStatusConstants.UNKNOWN) {
1236 throw new ImsException("getProvisionedBool failed with error for item: " + item,
1237 ImsReasonInfo.CODE_LOCAL_INTERNAL_ERROR);
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -07001238 }
Malcolm Chen18837ff2017-10-25 17:05:41 -07001239 return config.getProvisionedValue(item) == ImsConfig.FeatureValueConstants.ON;
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -07001240 }
1241
1242 /**
Malcolm Chen18837ff2017-10-25 17:05:41 -07001243 * Will return with config value or return false if we receive an error from
1244 * ImsConfig for that value.
Brad Ebingerbe6cb672017-08-25 14:55:00 -07001245 */
Malcolm Chen18837ff2017-10-25 17:05:41 -07001246 private boolean getProvisionedBoolNoException(int item) {
1247 try {
1248 ImsConfig config = getConfigInterface();
1249 return getProvisionedBool(config, item);
1250 } catch (ImsException ex) {
1251 return false;
Brad Ebingerbe6cb672017-08-25 14:55:00 -07001252 }
1253 }
1254
1255 /**
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001256 * Sync carrier config and user settings with ImsConfig.
1257 *
1258 * @param context for the manager object
1259 * @param phoneId phone id
1260 * @param force update
Brad Ebinger16417b42017-03-07 13:48:50 -08001261 *
Brad Ebinger479f52c2017-08-28 13:19:22 -07001262 * @deprecated Doesn't support MSIM devices. Use {@link #updateImsServiceConfig(boolean)}
1263 * instead.
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001264 */
1265 public static void updateImsServiceConfig(Context context, int phoneId, boolean force) {
Brad Ebinger479f52c2017-08-28 13:19:22 -07001266 ImsManager mgr = ImsManager.getInstance(context, phoneId);
1267 if (mgr != null) {
1268 mgr.updateImsServiceConfig(force);
Pavel Zhamaitsiakfc202992016-03-29 18:07:38 -07001269 }
Brad Ebinger479f52c2017-08-28 13:19:22 -07001270 loge("updateImsServiceConfig: ImsManager null, returning without update.");
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001271 }
1272
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -07001273 /**
Brad Ebinger16417b42017-03-07 13:48:50 -08001274 * Sync carrier config and user settings with ImsConfig.
1275 *
Brad Ebinger16417b42017-03-07 13:48:50 -08001276 * @param force update
1277 */
Brad Ebinger479f52c2017-08-28 13:19:22 -07001278 public void updateImsServiceConfig(boolean force) {
Brad Ebinger16417b42017-03-07 13:48:50 -08001279 if (!force) {
Brad Ebinger479f52c2017-08-28 13:19:22 -07001280 TelephonyManager tm = new TelephonyManager(mContext, getSubId());
1281 if (tm.getSimState() != TelephonyManager.SIM_STATE_READY) {
1282 log("updateImsServiceConfig: SIM not ready");
Brad Ebinger16417b42017-03-07 13:48:50 -08001283 // Don't disable IMS if SIM is not ready
1284 return;
1285 }
1286 }
1287
1288 if (!mConfigUpdated || force) {
1289 try {
Brad Ebinger16417b42017-03-07 13:48:50 -08001290 // TODO: Extend ImsConfig API and set all feature values in single function call.
1291
1292 // Note: currently the order of updates is set to produce different order of
Brad Ebinger172977a2018-01-16 09:36:56 -08001293 // changeEnabledCapabilities() function calls from setAdvanced4GMode(). This is done
1294 // to differentiate this code path from vendor code perspective.
Brad Ebinger16417b42017-03-07 13:48:50 -08001295 boolean isImsUsed = updateVolteFeatureValue();
1296 isImsUsed |= updateWfcFeatureAndProvisionedValues();
1297 isImsUsed |= updateVideoCallFeatureValue();
1298
Brad Ebinger479f52c2017-08-28 13:19:22 -07001299 if (isImsUsed || !isTurnOffImsAllowedByPlatform()) {
Brad Ebinger16417b42017-03-07 13:48:50 -08001300 // Turn on IMS if it is used.
1301 // Also, if turning off is not allowed for current carrier,
1302 // we need to turn IMS on because it might be turned off before
1303 // phone switched to current carrier.
Brad Ebinger479f52c2017-08-28 13:19:22 -07001304 log("updateImsServiceConfig: turnOnIms");
Brad Ebinger16417b42017-03-07 13:48:50 -08001305 turnOnIms();
1306 } else {
1307 // Turn off IMS if it is not used AND turning off is allowed for carrier.
Brad Ebinger479f52c2017-08-28 13:19:22 -07001308 log("updateImsServiceConfig: turnOffIms");
Brad Ebinger16417b42017-03-07 13:48:50 -08001309 turnOffIms();
1310 }
1311
1312 mConfigUpdated = true;
Brad Ebinger172977a2018-01-16 09:36:56 -08001313 } catch (ImsException | RemoteException e) {
Brad Ebinger479f52c2017-08-28 13:19:22 -07001314 loge("updateImsServiceConfig: ", e);
Brad Ebinger16417b42017-03-07 13:48:50 -08001315 mConfigUpdated = false;
1316 }
1317 }
1318 }
1319
1320 /**
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -07001321 * Update VoLTE config
1322 * @return whether feature is On
1323 * @throws ImsException
1324 */
Brad Ebinger172977a2018-01-16 09:36:56 -08001325 private boolean updateVolteFeatureValue() throws RemoteException {
Brad Ebinger479f52c2017-08-28 13:19:22 -07001326 boolean available = isVolteEnabledByPlatform();
1327 boolean enabled = isEnhanced4gLteModeSettingEnabledByUser();
1328 boolean isNonTty = isNonTtyOrTtyOnVolteEnabled();
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -08001329 boolean isFeatureOn = available && enabled && isNonTty;
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001330
1331 log("updateVolteFeatureValue: available = " + available
1332 + ", enabled = " + enabled
1333 + ", nonTTY = " + isNonTty);
1334
Brad Ebinger172977a2018-01-16 09:36:56 -08001335 changeMmTelCapability(MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE,
1336 ImsRegistrationImplBase.REGISTRATION_TECH_LTE, isFeatureOn);
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -07001337
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -08001338 return isFeatureOn;
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001339 }
1340
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -07001341 /**
Jack Yu643ffe42016-07-08 14:25:46 -07001342 * Update video call over LTE config
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -07001343 * @return whether feature is On
1344 * @throws ImsException
1345 */
Brad Ebinger172977a2018-01-16 09:36:56 -08001346 private boolean updateVideoCallFeatureValue() throws RemoteException {
Brad Ebinger479f52c2017-08-28 13:19:22 -07001347 boolean available = isVtEnabledByPlatform();
1348 boolean enabled = isVtEnabledByUser();
1349 boolean isNonTty = isNonTtyOrTtyOnVolteEnabled();
Amit Mahajan24f7b162016-07-21 16:33:53 -07001350 boolean isDataEnabled = isDataEnabled();
Brad Ebinger479f52c2017-08-28 13:19:22 -07001351 boolean ignoreDataEnabledChanged = getBooleanCarrierConfig(
Jack Yu57781852016-11-16 17:20:38 -08001352 CarrierConfigManager.KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS);
Jack Yu643ffe42016-07-08 14:25:46 -07001353
Jack Yu57781852016-11-16 17:20:38 -08001354 boolean isFeatureOn = available && enabled && isNonTty
1355 && (ignoreDataEnabledChanged || isDataEnabled);
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001356
1357 log("updateVideoCallFeatureValue: available = " + available
1358 + ", enabled = " + enabled
Jack Yu643ffe42016-07-08 14:25:46 -07001359 + ", nonTTY = " + isNonTty
Amit Mahajan24f7b162016-07-21 16:33:53 -07001360 + ", data enabled = " + isDataEnabled);
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001361
Brad Ebinger172977a2018-01-16 09:36:56 -08001362 changeMmTelCapability(MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VIDEO,
1363 ImsRegistrationImplBase.REGISTRATION_TECH_LTE, isFeatureOn);
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -07001364
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -08001365 return isFeatureOn;
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001366 }
1367
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -07001368 /**
1369 * Update WFC config
1370 * @return whether feature is On
1371 * @throws ImsException
1372 */
Brad Ebinger172977a2018-01-16 09:36:56 -08001373 private boolean updateWfcFeatureAndProvisionedValues() throws RemoteException {
Brad Ebinger479f52c2017-08-28 13:19:22 -07001374 TelephonyManager tm = new TelephonyManager(mContext, getSubId());
1375 boolean isNetworkRoaming = tm.isNetworkRoaming();
1376 boolean available = isWfcEnabledByPlatform();
1377 boolean enabled = isWfcEnabledByUser();
Suresh Koleti76491082017-04-21 18:39:50 +05301378 updateDefaultWfcMode();
Brad Ebinger479f52c2017-08-28 13:19:22 -07001379 int mode = getWfcMode(isNetworkRoaming);
1380 boolean roaming = isWfcRoamingEnabledByUser();
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -08001381 boolean isFeatureOn = available && enabled;
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001382
1383 log("updateWfcFeatureAndProvisionedValues: available = " + available
1384 + ", enabled = " + enabled
1385 + ", mode = " + mode
1386 + ", roaming = " + roaming);
1387
Brad Ebinger172977a2018-01-16 09:36:56 -08001388 changeMmTelCapability(MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE,
1389 ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN, isFeatureOn);
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001390
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -08001391 if (!isFeatureOn) {
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001392 mode = ImsConfig.WfcModeFeatureValueConstants.CELLULAR_PREFERRED;
1393 roaming = false;
1394 }
1395 setWfcModeInternal(mContext, mode);
Brad Ebinger16417b42017-03-07 13:48:50 -08001396 setWfcRoamingSettingInternal(roaming);
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -07001397
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -08001398 return isFeatureOn;
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001399 }
1400
Brad Ebinger16780ff2017-01-26 11:18:21 -08001401 /**
Brad Ebinger479f52c2017-08-28 13:19:22 -07001402 * Do NOT use this directly, instead use {@link #getInstance(Context, int)}.
Brad Ebinger16780ff2017-01-26 11:18:21 -08001403 */
1404 @VisibleForTesting
1405 public ImsManager(Context context, int phoneId) {
Wink Savilleef36ef62014-06-11 08:39:38 -07001406 mContext = context;
Etan Cohenabbd7882014-09-26 22:35:35 -07001407 mPhoneId = phoneId;
Brad Ebinger16780ff2017-01-26 11:18:21 -08001408 mConfigDynamicBind = mContext.getResources().getBoolean(
1409 com.android.internal.R.bool.config_dynamic_bind_ims);
Brad Ebinger16417b42017-03-07 13:48:50 -08001410 mConfigManager = (CarrierConfigManager) context.getSystemService(
1411 Context.CARRIER_CONFIG_SERVICE);
Brad Ebinger16780ff2017-01-26 11:18:21 -08001412 createImsService();
1413 }
1414
1415 /**
Brad Ebinger16780ff2017-01-26 11:18:21 -08001416 * @return Whether or not ImsManager is configured to Dynamically bind or not to support legacy
1417 * devices.
1418 */
1419 public boolean isDynamicBinding() {
1420 return mConfigDynamicBind;
Wink Savilleef36ef62014-06-11 08:39:38 -07001421 }
1422
Etan Cohenf4311122015-02-26 17:47:13 -08001423 /*
Brad Ebingerff097922017-06-19 15:43:08 -07001424 * Returns a flag indicating whether the IMS service is available. If it is not available,
1425 * it will try to connect before reporting failure.
Etan Cohenf4311122015-02-26 17:47:13 -08001426 */
1427 public boolean isServiceAvailable() {
Brad Ebingerff097922017-06-19 15:43:08 -07001428 connectIfServiceIsAvailable();
Brad Ebinger16780ff2017-01-26 11:18:21 -08001429 // mImsServiceProxy will always create an ImsServiceProxy.
Brad Ebinger172977a2018-01-16 09:36:56 -08001430 return mMmTelFeatureConnection.isBinderAlive();
Etan Cohenf4311122015-02-26 17:47:13 -08001431 }
1432
Suresh Koleticc3139c2017-11-03 18:23:57 +05301433 /*
1434 * Returns a flag indicating whether the IMS service is ready to send requests to lower layers.
1435 */
1436 public boolean isServiceReady() {
1437 connectIfServiceIsAvailable();
Brad Ebinger172977a2018-01-16 09:36:56 -08001438 return mMmTelFeatureConnection.isBinderReady();
Suresh Koleticc3139c2017-11-03 18:23:57 +05301439 }
1440
Brad Ebingerff097922017-06-19 15:43:08 -07001441 /**
1442 * If the service is available, try to reconnect.
1443 */
1444 public void connectIfServiceIsAvailable() {
Brad Ebinger172977a2018-01-16 09:36:56 -08001445 if (mMmTelFeatureConnection == null || !mMmTelFeatureConnection.isBinderAlive()) {
Brad Ebingerff097922017-06-19 15:43:08 -07001446 createImsService();
1447 }
1448 }
1449
Brad Ebinger172977a2018-01-16 09:36:56 -08001450 public void setConfigListener(ImsConfigListener listener) {
Pavel Zhamaitsiakf4b90322016-01-26 14:34:09 -08001451 mImsConfigListener = listener;
1452 }
1453
Brad Ebingerb10b61e2017-04-18 11:45:26 -07001454
1455 /**
1456 * Adds a callback for status changed events if the binder is already available. If it is not,
1457 * this method will throw an ImsException.
1458 */
Brad Ebinger6ddf28e2018-02-21 16:07:23 -08001459 @VisibleForTesting
Brad Ebinger172977a2018-01-16 09:36:56 -08001460 public void addNotifyStatusChangedCallbackIfAvailable(MmTelFeatureConnection.IFeatureUpdate c)
Brad Ebingerb10b61e2017-04-18 11:45:26 -07001461 throws ImsException {
Brad Ebinger172977a2018-01-16 09:36:56 -08001462 if (!mMmTelFeatureConnection.isBinderAlive()) {
Brad Ebingerb10b61e2017-04-18 11:45:26 -07001463 throw new ImsException("Binder is not active!",
1464 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1465 }
Brad Ebinger16780ff2017-01-26 11:18:21 -08001466 if (c != null) {
1467 mStatusCallbacks.add(c);
1468 }
1469 }
1470
Brad Ebinger6ddf28e2018-02-21 16:07:23 -08001471 void removeNotifyStatusChangedCallback(MmTelFeatureConnection.IFeatureUpdate c) {
Brad Ebinger44fd8af2017-12-14 14:24:02 -08001472 if (c != null) {
1473 mStatusCallbacks.remove(c);
1474 } else {
1475 Log.w(TAG, "removeNotifyStatusChangedCallback: callback is null!");
1476 }
1477 }
1478
Wink Savilleef36ef62014-06-11 08:39:38 -07001479 /**
1480 * Opens the IMS service for making calls and/or receiving generic IMS calls.
Brad Ebinger172977a2018-01-16 09:36:56 -08001481 * The caller may make subsequent calls through {@link #makeCall}.
Wink Savilleef36ef62014-06-11 08:39:38 -07001482 * The IMS service will register the device to the operator's network with the credentials
1483 * (from ISIM) periodically in order to receive calls from the operator's network.
Brad Ebinger172977a2018-01-16 09:36:56 -08001484 * When the IMS service receives a new call, it will call
1485 * {@link MmTelFeature.Listener#onIncomingCall}
1486 * The listener contains a call ID extra {@link #getCallId} and it can be used to take a call.
1487 * @param listener A {@link MmTelFeature.Listener}, which is the interface the
1488 * {@link MmTelFeature} uses to notify the framework of updates
1489 * @throws NullPointerException if {@code listener} is null
Wink Savilleef36ef62014-06-11 08:39:38 -07001490 * @throws ImsException if calling the IMS service results in an error
1491 * @see #getCallId
Wink Savilleef36ef62014-06-11 08:39:38 -07001492 */
Brad Ebinger172977a2018-01-16 09:36:56 -08001493 public void open(MmTelFeature.Listener listener) throws ImsException {
Wink Savilleef36ef62014-06-11 08:39:38 -07001494 checkAndThrowExceptionIfServiceUnavailable();
1495
Wink Savilleef36ef62014-06-11 08:39:38 -07001496 if (listener == null) {
1497 throw new NullPointerException("listener can't be null");
1498 }
1499
Wink Savilleef36ef62014-06-11 08:39:38 -07001500 try {
Brad Ebinger172977a2018-01-16 09:36:56 -08001501 mMmTelFeatureConnection.openConnection(listener);
Wink Savilleef36ef62014-06-11 08:39:38 -07001502 } catch (RemoteException e) {
Brad Ebinger172977a2018-01-16 09:36:56 -08001503 throw new ImsException("open()", e, ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
Wink Savilleef36ef62014-06-11 08:39:38 -07001504 }
Wink Savilleef36ef62014-06-11 08:39:38 -07001505 }
1506
1507 /**
Pavel Zhamaitsiakce410172016-04-15 10:55:56 -07001508 * Adds registration listener to the IMS service.
1509 *
1510 * @param serviceClass a service class specified in {@link ImsServiceClass}
1511 * For VoLTE service, it MUST be a {@link ImsServiceClass#MMTEL}.
1512 * @param listener To listen to IMS registration events; It cannot be null
1513 * @throws NullPointerException if {@code listener} is null
1514 * @throws ImsException if calling the IMS service results in an error
Brad Ebinger9a0280c2017-06-01 15:58:48 -07001515 *
1516 * @deprecated Use {@link #addRegistrationListener(ImsConnectionStateListener)} instead.
Pavel Zhamaitsiakce410172016-04-15 10:55:56 -07001517 */
1518 public void addRegistrationListener(int serviceClass, ImsConnectionStateListener listener)
1519 throws ImsException {
Brad Ebinger9a0280c2017-06-01 15:58:48 -07001520 addRegistrationListener(listener);
1521 }
1522
1523 /**
1524 * Adds registration listener to the IMS service.
1525 *
1526 * @param listener To listen to IMS registration events; It cannot be null
1527 * @throws NullPointerException if {@code listener} is null
1528 * @throws ImsException if calling the IMS service results in an error
Brad Ebinger172977a2018-01-16 09:36:56 -08001529 * @deprecated use {@link #addRegistrationCallback(ImsRegistrationImplBase.Callback)} and
1530 * {@link #addCapabilitiesCallback(ImsFeature.CapabilityCallback)} instead.
Brad Ebinger9a0280c2017-06-01 15:58:48 -07001531 */
Brad Ebinger44fd8af2017-12-14 14:24:02 -08001532 public void addRegistrationListener(ImsConnectionStateListener listener) throws ImsException {
Pavel Zhamaitsiakce410172016-04-15 10:55:56 -07001533 if (listener == null) {
1534 throw new NullPointerException("listener can't be null");
1535 }
Brad Ebinger172977a2018-01-16 09:36:56 -08001536 addRegistrationCallback(listener);
1537 // connect the ImsConnectionStateListener to the new CapabilityCallback.
1538 addCapabilitiesCallback(new ImsFeature.CapabilityCallback() {
1539 @Override
1540 public void onCapabilitiesStatusChanged(ImsFeature.Capabilities config) {
1541 listener.onFeatureCapabilityChangedAdapter(getRegistrationTech(), config);
Brad Ebinger9a0280c2017-06-01 15:58:48 -07001542 }
Brad Ebinger172977a2018-01-16 09:36:56 -08001543 });
1544 log("Registration Callback registered.");
1545 }
1546
1547 /**
1548 * Adds a callback that gets called when IMS registration has changed.
1549 * @param callback A {@link ImsRegistrationImplBase.Callback} that will notify the caller when
1550 * IMS registration status has changed.
1551 * @throws ImsException when the ImsService connection is not available.
1552 */
1553 public void addRegistrationCallback(ImsRegistrationImplBase.Callback callback)
1554 throws ImsException {
1555 if (callback == null) {
1556 throw new NullPointerException("registration callback can't be null");
Brad Ebinger9a0280c2017-06-01 15:58:48 -07001557 }
Brad Ebinger172977a2018-01-16 09:36:56 -08001558
Brad Ebinger172977a2018-01-16 09:36:56 -08001559 try {
1560 mMmTelFeatureConnection.addRegistrationCallback(callback);
1561 log("Registration Callback registered.");
1562 // Only record if there isn't a RemoteException.
1563 } catch (RemoteException e) {
1564 throw new ImsException("addRegistrationCallback(IRIB)", e,
1565 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1566 }
1567 }
1568
1569 /**
Brad Ebingerd1b1a3c2018-03-08 11:37:35 -08001570 * Removes a previously added registration callback that was added via
1571 * {@link #addRegistrationCallback(ImsRegistrationImplBase.Callback)} .
1572 * @param callback A {@link ImsRegistrationImplBase.Callback} that was previously added.
1573 * @throws ImsException when the ImsService connection is not available.
1574 */
1575 public void removeRegistrationListener(ImsRegistrationImplBase.Callback callback)
1576 throws ImsException {
1577 if (callback == null) {
1578 throw new NullPointerException("registration callback can't be null");
1579 }
1580
1581 try {
1582 mMmTelFeatureConnection.removeRegistrationCallback(callback);
1583 log("Registration callback removed.");
1584 } catch (RemoteException e) {
1585 throw new ImsException("removeRegistrationCallback(IRIB)", e,
1586 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1587 }
1588 }
1589
1590 /**
Brad Ebinger172977a2018-01-16 09:36:56 -08001591 * Adds a callback that gets called when MMTel capability status has changed, for example when
1592 * Voice over IMS or VT over IMS is not available currently.
1593 * @param callback A {@link ImsFeature.CapabilityCallback} that will notify the caller when
1594 * MMTel capability status has changed.
1595 * @throws ImsException when the ImsService connection is not available.
1596 */
1597 public void addCapabilitiesCallback(ImsFeature.CapabilityCallback callback)
1598 throws ImsException {
1599 if (callback == null) {
1600 throw new NullPointerException("capabilities callback can't be null");
1601 }
1602
1603 checkAndThrowExceptionIfServiceUnavailable();
1604 try {
1605 mMmTelFeatureConnection.addCapabilityCallback(callback);
1606 log("Capability Callback registered.");
1607 // Only record if there isn't a RemoteException.
1608 } catch (RemoteException e) {
1609 throw new ImsException("addCapabilitiesCallback(IF)", e,
1610 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
Pavel Zhamaitsiakce410172016-04-15 10:55:56 -07001611 }
1612 }
1613
1614 /**
Brad Ebinger16780ff2017-01-26 11:18:21 -08001615 * Removes the registration listener from the IMS service.
1616 *
Brad Ebinger16780ff2017-01-26 11:18:21 -08001617 * @param listener Previously registered listener that will be removed. Can not be null.
1618 * @throws NullPointerException if {@code listener} is null
1619 * @throws ImsException if calling the IMS service results in an error
1620 * instead.
1621 */
Brad Ebingerb5f30c72017-02-17 14:54:31 -08001622 public void removeRegistrationListener(ImsConnectionStateListener listener)
Brad Ebinger16780ff2017-01-26 11:18:21 -08001623 throws ImsException {
Brad Ebinger16780ff2017-01-26 11:18:21 -08001624 if (listener == null) {
1625 throw new NullPointerException("listener can't be null");
1626 }
1627
Brad Ebinger172977a2018-01-16 09:36:56 -08001628 checkAndThrowExceptionIfServiceUnavailable();
1629 try {
1630 mMmTelFeatureConnection.removeRegistrationCallback(listener);
1631 log("Registration Callback/Listener registered.");
1632 // Only record if there isn't a RemoteException.
1633 } catch (RemoteException e) {
1634 throw new ImsException("addRegistrationCallback()", e,
1635 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1636 }
1637 }
1638
1639 public @ImsRegistrationImplBase.ImsRegistrationTech int getRegistrationTech() {
1640 try {
1641 return mMmTelFeatureConnection.getRegistrationTech();
1642 } catch (RemoteException e) {
1643 Log.w(TAG, "getRegistrationTech: no connection to ImsService.");
1644 return ImsRegistrationImplBase.REGISTRATION_TECH_NONE;
Brad Ebinger16780ff2017-01-26 11:18:21 -08001645 }
1646 }
1647
1648 /**
Brad Ebinger172977a2018-01-16 09:36:56 -08001649 * Closes the connection and removes all active callbacks.
Wink Savilleef36ef62014-06-11 08:39:38 -07001650 * All the resources that were allocated to the service are also released.
Wink Savilleef36ef62014-06-11 08:39:38 -07001651 */
Brad Ebinger172977a2018-01-16 09:36:56 -08001652 public void close() {
1653 if (mMmTelFeatureConnection != null) {
1654 mMmTelFeatureConnection.closeConnection();
Wink Savilleef36ef62014-06-11 08:39:38 -07001655 }
Brad Ebinger172977a2018-01-16 09:36:56 -08001656 mUt = null;
1657 mConfig = null;
1658 mEcbm = null;
1659 mMultiEndpoint = null;
Wink Savilleef36ef62014-06-11 08:39:38 -07001660 }
1661
1662 /**
1663 * Gets the configuration interface to provision / withdraw the supplementary service settings.
1664 *
Wink Savilleef36ef62014-06-11 08:39:38 -07001665 * @return the Ut interface instance
1666 * @throws ImsException if getting the Ut interface results in an error
1667 */
Brad Ebinger172977a2018-01-16 09:36:56 -08001668 public ImsUtInterface getSupplementaryServiceConfiguration() throws ImsException {
Brad Ebinger16780ff2017-01-26 11:18:21 -08001669 // FIXME: manage the multiple Ut interfaces based on the session id
Brad Ebinger138b4a62017-06-20 16:29:50 -07001670 if (mUt != null && mUt.isBinderAlive()) {
1671 return mUt;
Wink Savilleef36ef62014-06-11 08:39:38 -07001672 }
1673
Brad Ebinger138b4a62017-06-20 16:29:50 -07001674 checkAndThrowExceptionIfServiceUnavailable();
1675 try {
Brad Ebinger172977a2018-01-16 09:36:56 -08001676 IImsUt iUt = mMmTelFeatureConnection.getUtInterface();
Brad Ebinger138b4a62017-06-20 16:29:50 -07001677
1678 if (iUt == null) {
1679 throw new ImsException("getSupplementaryServiceConfiguration()",
1680 ImsReasonInfo.CODE_UT_NOT_SUPPORTED);
1681 }
1682
1683 mUt = new ImsUt(iUt);
1684 } catch (RemoteException e) {
1685 throw new ImsException("getSupplementaryServiceConfiguration()", e,
1686 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1687 }
Wink Savilleef36ef62014-06-11 08:39:38 -07001688 return mUt;
1689 }
1690
1691 /**
Wink Savilleef36ef62014-06-11 08:39:38 -07001692 * Creates a {@link ImsCallProfile} from the service capabilities & IMS registration state.
1693 *
Wink Savilleef36ef62014-06-11 08:39:38 -07001694 * @param serviceType a service type that is specified in {@link ImsCallProfile}
1695 * {@link ImsCallProfile#SERVICE_TYPE_NONE}
1696 * {@link ImsCallProfile#SERVICE_TYPE_NORMAL}
1697 * {@link ImsCallProfile#SERVICE_TYPE_EMERGENCY}
1698 * @param callType a call type that is specified in {@link ImsCallProfile}
1699 * {@link ImsCallProfile#CALL_TYPE_VOICE}
1700 * {@link ImsCallProfile#CALL_TYPE_VT}
1701 * {@link ImsCallProfile#CALL_TYPE_VT_TX}
1702 * {@link ImsCallProfile#CALL_TYPE_VT_RX}
1703 * {@link ImsCallProfile#CALL_TYPE_VT_NODIR}
1704 * {@link ImsCallProfile#CALL_TYPE_VS}
1705 * {@link ImsCallProfile#CALL_TYPE_VS_TX}
1706 * {@link ImsCallProfile#CALL_TYPE_VS_RX}
1707 * @return a {@link ImsCallProfile} object
1708 * @throws ImsException if calling the IMS service results in an error
1709 */
Brad Ebinger172977a2018-01-16 09:36:56 -08001710 public ImsCallProfile createCallProfile(int serviceType, int callType) throws ImsException {
Wink Savilleef36ef62014-06-11 08:39:38 -07001711 checkAndThrowExceptionIfServiceUnavailable();
1712
1713 try {
Brad Ebinger172977a2018-01-16 09:36:56 -08001714 return mMmTelFeatureConnection.createCallProfile(serviceType, callType);
Wink Savilleef36ef62014-06-11 08:39:38 -07001715 } catch (RemoteException e) {
1716 throw new ImsException("createCallProfile()", e,
1717 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1718 }
1719 }
1720
1721 /**
1722 * Creates a {@link ImsCall} to make a call.
1723 *
Wink Savilleef36ef62014-06-11 08:39:38 -07001724 * @param profile a call profile to make the call
1725 * (it contains service type, call type, media information, etc.)
Brad Ebinger172977a2018-01-16 09:36:56 -08001726 * @param callees participants to invite the conference call
Wink Savilleef36ef62014-06-11 08:39:38 -07001727 * @param listener listen to the call events from {@link ImsCall}
1728 * @return a {@link ImsCall} object
1729 * @throws ImsException if calling the IMS service results in an error
1730 */
Brad Ebinger172977a2018-01-16 09:36:56 -08001731 public ImsCall makeCall(ImsCallProfile profile, String[] callees,
Wink Savilleef36ef62014-06-11 08:39:38 -07001732 ImsCall.Listener listener) throws ImsException {
1733 if (DBG) {
Brad Ebinger172977a2018-01-16 09:36:56 -08001734 log("makeCall :: profile=" + profile);
Wink Savilleef36ef62014-06-11 08:39:38 -07001735 }
1736
1737 checkAndThrowExceptionIfServiceUnavailable();
1738
1739 ImsCall call = new ImsCall(mContext, profile);
1740
1741 call.setListener(listener);
Brad Ebinger172977a2018-01-16 09:36:56 -08001742 ImsCallSession session = createCallSession(profile);
Wink Savilleef36ef62014-06-11 08:39:38 -07001743
1744 if ((callees != null) && (callees.length == 1)) {
1745 call.start(session, callees[0]);
1746 } else {
1747 call.start(session, callees);
1748 }
1749
1750 return call;
1751 }
1752
1753 /**
1754 * Creates a {@link ImsCall} to take an incoming call.
1755 *
Brad Ebinger16780ff2017-01-26 11:18:21 -08001756 * @param sessionId a session id which is obtained from {@link ImsManager#open}
Brad Ebinger172977a2018-01-16 09:36:56 -08001757 * @param incomingCallExtras the incoming call broadcast intent
Wink Savilleef36ef62014-06-11 08:39:38 -07001758 * @param listener to listen to the call events from {@link ImsCall}
1759 * @return a {@link ImsCall} object
1760 * @throws ImsException if calling the IMS service results in an error
1761 */
Brad Ebinger172977a2018-01-16 09:36:56 -08001762 public ImsCall takeCall(IImsCallSession session, Bundle incomingCallExtras,
Wink Savilleef36ef62014-06-11 08:39:38 -07001763 ImsCall.Listener listener) throws ImsException {
1764 if (DBG) {
Brad Ebinger172977a2018-01-16 09:36:56 -08001765 log("takeCall :: incomingCall=" + incomingCallExtras);
Wink Savilleef36ef62014-06-11 08:39:38 -07001766 }
1767
1768 checkAndThrowExceptionIfServiceUnavailable();
1769
Brad Ebinger172977a2018-01-16 09:36:56 -08001770 if (incomingCallExtras == null) {
Wink Savilleef36ef62014-06-11 08:39:38 -07001771 throw new ImsException("Can't retrieve session with null intent",
1772 ImsReasonInfo.CODE_LOCAL_ILLEGAL_ARGUMENT);
1773 }
1774
Brad Ebinger172977a2018-01-16 09:36:56 -08001775 String callId = getCallId(incomingCallExtras);
Wink Savilleef36ef62014-06-11 08:39:38 -07001776
1777 if (callId == null) {
1778 throw new ImsException("Call ID missing in the incoming call intent",
1779 ImsReasonInfo.CODE_LOCAL_ILLEGAL_ARGUMENT);
1780 }
1781
1782 try {
Wink Savilleef36ef62014-06-11 08:39:38 -07001783 if (session == null) {
1784 throw new ImsException("No pending session for the call",
1785 ImsReasonInfo.CODE_LOCAL_NO_PENDING_CALL);
1786 }
1787
1788 ImsCall call = new ImsCall(mContext, session.getCallProfile());
1789
1790 call.attachSession(new ImsCallSession(session));
1791 call.setListener(listener);
1792
1793 return call;
1794 } catch (Throwable t) {
1795 throw new ImsException("takeCall()", t, ImsReasonInfo.CODE_UNSPECIFIED);
1796 }
1797 }
1798
1799 /**
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -05001800 * Gets the config interface to get/set service/capability parameters.
1801 *
1802 * @return the ImsConfig instance.
1803 * @throws ImsException if getting the setting interface results in an error.
1804 */
1805 public ImsConfig getConfigInterface() throws ImsException {
Brad Ebinger138b4a62017-06-20 16:29:50 -07001806 if (mConfig != null && mConfig.isBinderAlive()) {
1807 return mConfig;
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -05001808 }
Brad Ebinger138b4a62017-06-20 16:29:50 -07001809
1810 checkAndThrowExceptionIfServiceUnavailable();
1811 try {
Brad Ebinger172977a2018-01-16 09:36:56 -08001812 IImsConfig config = mMmTelFeatureConnection.getConfigInterface();
Brad Ebinger138b4a62017-06-20 16:29:50 -07001813 if (config == null) {
1814 throw new ImsException("getConfigInterface()",
1815 ImsReasonInfo.CODE_LOCAL_SERVICE_UNAVAILABLE);
1816 }
1817 mConfig = new ImsConfig(config, mContext);
1818 } catch (RemoteException e) {
1819 throw new ImsException("getConfigInterface()", e,
1820 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1821 }
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -05001822 return mConfig;
1823 }
1824
Brad Ebinger172977a2018-01-16 09:36:56 -08001825 public void changeMmTelCapability(
1826 @MmTelFeature.MmTelCapabilities.MmTelCapability int capability,
1827 @ImsRegistrationImplBase.ImsRegistrationTech int radioTech,
1828 boolean isEnabled) throws RemoteException {
1829 CapabilityChangeRequest request = new CapabilityChangeRequest();
1830 if (isEnabled) {
1831 request.addCapabilitiesToEnableForTech(capability, radioTech);
1832 } else {
1833 request.addCapabilitiesToDisableForTech(capability, radioTech);
1834 }
1835 mMmTelFeatureConnection.changeEnabledCapabilities(request, null);
1836 if (mImsConfigListener != null) {
1837 mImsConfigListener.onSetFeatureResponse(capability,
1838 mMmTelFeatureConnection.getRegistrationTech(),
1839 isEnabled ? ImsConfig.FeatureValueConstants.ON
1840 : ImsConfig.FeatureValueConstants.OFF, -1);
1841 }
1842 }
1843
Hall Liub77d8972018-01-22 19:15:05 -08001844 public void setRttEnabled(boolean enabled) {
1845 try {
1846 setAdvanced4GMode(enabled || isEnhanced4gLteModeSettingEnabledByUser());
1847 final int value = enabled ? ImsConfig.FeatureValueConstants.ON :
1848 ImsConfig.FeatureValueConstants.OFF;
1849 Thread thread = new Thread(() -> {
1850 try {
1851 Log.i(ImsManager.class.getSimpleName(), "Setting RTT enabled to " + enabled);
1852 getConfigInterface().setProvisionedValue(
1853 ImsConfig.ConfigConstants.RTT_SETTING_ENABLED, value);
1854 } catch (ImsException e) {
1855 Log.e(ImsManager.class.getSimpleName(), "Unable to set RTT enabled to "
1856 + enabled + ": " + e);
1857 }
1858 });
1859 thread.start();
1860 } catch (ImsException e) {
1861 Log.e(ImsManager.class.getSimpleName(), "Unable to set RTT enabled to " + enabled
1862 + ": " + e);
1863 }
1864 }
1865
Hall Liue511a202017-08-17 15:49:58 -07001866 /**
1867 * Set the TTY mode. This is the actual tty mode (varies depending on peripheral status)
1868 */
1869 public void setTtyMode(int ttyMode) throws ImsException {
Brad Ebinger479f52c2017-08-28 13:19:22 -07001870 if (!getBooleanCarrierConfig(
Hall Liue511a202017-08-17 15:49:58 -07001871 CarrierConfigManager.KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL)) {
1872 setAdvanced4GMode((ttyMode == TelecomManager.TTY_MODE_OFF) &&
Brad Ebinger479f52c2017-08-28 13:19:22 -07001873 isEnhanced4gLteModeSettingEnabledByUser());
Hall Liue511a202017-08-17 15:49:58 -07001874 }
1875 }
1876
1877 /**
1878 * Sets the UI TTY mode. This is the preferred TTY mode that the user sets in the call
1879 * settings screen.
1880 */
Brad Ebingerb5f30c72017-02-17 14:54:31 -08001881 public void setUiTTYMode(Context context, int uiTtyMode, Message onComplete)
Shriram Ganeshc403b7b2014-08-14 14:18:57 +05301882 throws ImsException {
1883
Etan Cohen82f78122014-12-15 10:10:14 -08001884 checkAndThrowExceptionIfServiceUnavailable();
Shriram Ganeshc403b7b2014-08-14 14:18:57 +05301885
Etan Cohen82f78122014-12-15 10:10:14 -08001886 try {
Brad Ebinger172977a2018-01-16 09:36:56 -08001887 mMmTelFeatureConnection.setUiTTYMode(uiTtyMode, onComplete);
Etan Cohen82f78122014-12-15 10:10:14 -08001888 } catch (RemoteException e) {
1889 throw new ImsException("setTTYMode()", e,
1890 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1891 }
Shriram Ganeshc403b7b2014-08-14 14:18:57 +05301892 }
1893
Naveen Kalla525c3a22017-02-06 14:46:42 -08001894 private ImsReasonInfo makeACopy(ImsReasonInfo imsReasonInfo) {
1895 Parcel p = Parcel.obtain();
1896 imsReasonInfo.writeToParcel(p, 0);
1897 p.setDataPosition(0);
1898 ImsReasonInfo clonedReasonInfo = ImsReasonInfo.CREATOR.createFromParcel(p);
1899 p.recycle();
1900 return clonedReasonInfo;
1901 }
1902
1903 /**
1904 * Get Recent IMS Disconnect Reasons.
1905 *
1906 * @return ArrayList of ImsReasonInfo objects. MAX size of the arraylist
1907 * is MAX_RECENT_DISCONNECT_REASONS. The objects are in the
1908 * chronological order.
1909 */
1910 public ArrayList<ImsReasonInfo> getRecentImsDisconnectReasons() {
1911 ArrayList<ImsReasonInfo> disconnectReasons = new ArrayList<>();
1912
1913 for (ImsReasonInfo reason : mRecentDisconnectReasons) {
1914 disconnectReasons.add(makeACopy(reason));
1915 }
1916 return disconnectReasons;
1917 }
Brad Ebinger16417b42017-03-07 13:48:50 -08001918
Brad Ebinger172977a2018-01-16 09:36:56 -08001919 public int getImsServiceState() throws ImsException {
1920 return mMmTelFeatureConnection.getFeatureState();
Brad Ebinger16780ff2017-01-26 11:18:21 -08001921 }
Naveen Kalla525c3a22017-02-06 14:46:42 -08001922
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -05001923 /**
Junda Liue7663c02015-06-23 11:16:26 -07001924 * Get the boolean config from carrier config manager.
1925 *
Brad Ebinger16417b42017-03-07 13:48:50 -08001926 * @param key config key defined in CarrierConfigManager
1927 * @return boolean value of corresponding key.
1928 */
Brad Ebinger479f52c2017-08-28 13:19:22 -07001929 private boolean getBooleanCarrierConfig(String key) {
Brad Ebinger16417b42017-03-07 13:48:50 -08001930 int[] subIds = SubscriptionManager.getSubId(mPhoneId);
1931 int subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1932 if (subIds != null && subIds.length >= 1) {
1933 subId = subIds[0];
1934 }
1935 PersistableBundle b = null;
1936 if (mConfigManager != null) {
1937 // If an invalid subId is used, this bundle will contain default values.
1938 b = mConfigManager.getConfigForSubId(subId);
1939 }
1940 if (b != null) {
1941 return b.getBoolean(key);
1942 } else {
1943 // Return static default defined in CarrierConfigManager.
1944 return CarrierConfigManager.getDefaultConfig().getBoolean(key);
1945 }
1946 }
1947
1948 /**
fionaxu5803ef02016-03-08 11:48:48 -08001949 * Get the int config from carrier config manager.
1950 *
Brad Ebinger16417b42017-03-07 13:48:50 -08001951 * @param key config key defined in CarrierConfigManager
1952 * @return integer value of corresponding key.
1953 */
Brad Ebinger479f52c2017-08-28 13:19:22 -07001954 private int getIntCarrierConfig(String key) {
Brad Ebinger16417b42017-03-07 13:48:50 -08001955 int[] subIds = SubscriptionManager.getSubId(mPhoneId);
1956 int subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1957 if (subIds != null && subIds.length >= 1) {
1958 subId = subIds[0];
1959 }
1960 PersistableBundle b = null;
1961 if (mConfigManager != null) {
1962 // If an invalid subId is used, this bundle will contain default values.
1963 b = mConfigManager.getConfigForSubId(subId);
1964 }
1965 if (b != null) {
1966 return b.getInt(key);
1967 } else {
1968 // Return static default defined in CarrierConfigManager.
1969 return CarrierConfigManager.getDefaultConfig().getInt(key);
1970 }
1971 }
1972
1973 /**
Wink Savilleef36ef62014-06-11 08:39:38 -07001974 * Gets the call ID from the specified incoming call broadcast intent.
1975 *
Brad Ebinger172977a2018-01-16 09:36:56 -08001976 * @param incomingCallExtras the incoming call broadcast intent
Wink Savilleef36ef62014-06-11 08:39:38 -07001977 * @return the call ID or null if the intent does not contain it
1978 */
Brad Ebinger172977a2018-01-16 09:36:56 -08001979 private static String getCallId(Bundle incomingCallExtras) {
1980 if (incomingCallExtras == null) {
Wink Savilleef36ef62014-06-11 08:39:38 -07001981 return null;
1982 }
1983
Brad Ebinger172977a2018-01-16 09:36:56 -08001984 return incomingCallExtras.getString(EXTRA_CALL_ID);
Wink Savilleef36ef62014-06-11 08:39:38 -07001985 }
1986
1987 /**
Brad Ebingerb10b61e2017-04-18 11:45:26 -07001988 * Checks to see if the ImsService Binder is connected. If it is not, we try to create the
1989 * connection again.
Wink Savilleef36ef62014-06-11 08:39:38 -07001990 */
1991 private void checkAndThrowExceptionIfServiceUnavailable()
1992 throws ImsException {
Brad Ebinger172977a2018-01-16 09:36:56 -08001993 if (mMmTelFeatureConnection == null || !mMmTelFeatureConnection.isBinderAlive()) {
Brad Ebinger16780ff2017-01-26 11:18:21 -08001994 createImsService();
Wink Savilleef36ef62014-06-11 08:39:38 -07001995
Brad Ebinger172977a2018-01-16 09:36:56 -08001996 if (mMmTelFeatureConnection == null) {
Wink Savilleef36ef62014-06-11 08:39:38 -07001997 throw new ImsException("Service is unavailable",
1998 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1999 }
2000 }
2001 }
2002
Brad Ebinger16780ff2017-01-26 11:18:21 -08002003 /**
2004 * Binds the IMS service to make/receive the call. Supports two methods of exposing an
2005 * ImsService:
2006 * 1) com.android.ims.ImsService implementation in ServiceManager (deprecated).
2007 * 2) android.telephony.ims.ImsService implementation through ImsResolver.
2008 */
2009 private void createImsService() {
Brad Ebinger172977a2018-01-16 09:36:56 -08002010 Rlog.i(TAG, "Creating ImsService");
2011 mMmTelFeatureConnection = MmTelFeatureConnection.create(mContext, mPhoneId);
2012
Brad Ebinger44fd8af2017-12-14 14:24:02 -08002013 // Forwarding interface to tell mStatusCallbacks that the Proxy is unavailable.
Brad Ebinger172977a2018-01-16 09:36:56 -08002014 mMmTelFeatureConnection.setStatusCallback(new MmTelFeatureConnection.IFeatureUpdate() {
Brad Ebinger44fd8af2017-12-14 14:24:02 -08002015 @Override
2016 public void notifyStateChanged() {
Brad Ebinger172977a2018-01-16 09:36:56 -08002017 mStatusCallbacks.forEach(MmTelFeatureConnection.IFeatureUpdate::notifyStateChanged);
Brad Ebinger44fd8af2017-12-14 14:24:02 -08002018 }
2019
2020 @Override
2021 public void notifyUnavailable() {
Brad Ebinger172977a2018-01-16 09:36:56 -08002022 mStatusCallbacks.forEach(MmTelFeatureConnection.IFeatureUpdate::notifyUnavailable);
Brad Ebinger44fd8af2017-12-14 14:24:02 -08002023 }
2024 });
Etan Cohend7727462014-07-12 14:54:10 -07002025 }
2026
Wink Savilleef36ef62014-06-11 08:39:38 -07002027 /**
2028 * Creates a {@link ImsCallSession} with the specified call profile.
2029 * Use other methods, if applicable, instead of interacting with
2030 * {@link ImsCallSession} directly.
2031 *
Wink Savilleef36ef62014-06-11 08:39:38 -07002032 * @param profile a call profile to make the call
2033 */
Brad Ebinger172977a2018-01-16 09:36:56 -08002034 private ImsCallSession createCallSession(ImsCallProfile profile) throws ImsException {
Wink Savilleef36ef62014-06-11 08:39:38 -07002035 try {
Brad Ebingerb10b61e2017-04-18 11:45:26 -07002036 // Throws an exception if the ImsService Feature is not ready to accept commands.
Brad Ebinger172977a2018-01-16 09:36:56 -08002037 return new ImsCallSession(mMmTelFeatureConnection.createCallSession(profile));
Wink Savilleef36ef62014-06-11 08:39:38 -07002038 } catch (RemoteException e) {
Brad Ebingerb10b61e2017-04-18 11:45:26 -07002039 Rlog.w(TAG, "CreateCallSession: Error, remote exception: " + e.getMessage());
2040 throw new ImsException("createCallSession()", e,
2041 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
2042
Wink Savilleef36ef62014-06-11 08:39:38 -07002043 }
2044 }
2045
Etan Cohena00c9192014-12-23 15:02:29 -08002046 private static void log(String s) {
Wink Savilleef36ef62014-06-11 08:39:38 -07002047 Rlog.d(TAG, s);
2048 }
2049
Etan Cohena00c9192014-12-23 15:02:29 -08002050 private static void loge(String s) {
Wink Savilleef36ef62014-06-11 08:39:38 -07002051 Rlog.e(TAG, s);
2052 }
2053
Etan Cohena00c9192014-12-23 15:02:29 -08002054 private static void loge(String s, Throwable t) {
Wink Savilleef36ef62014-06-11 08:39:38 -07002055 Rlog.e(TAG, s, t);
2056 }
2057
2058 /**
ram7da5a112014-07-16 20:59:27 +05302059 * Used for turning on IMS.if its off already
2060 */
Etan Cohen82f78122014-12-15 10:10:14 -08002061 private void turnOnIms() throws ImsException {
Brad Ebinger172977a2018-01-16 09:36:56 -08002062 TelephonyManager tm = (TelephonyManager)
2063 mContext.getSystemService(Context.TELEPHONY_SERVICE);
2064 tm.enableIms(mPhoneId);
ram7da5a112014-07-16 20:59:27 +05302065 }
2066
Omkar Kolangade75f3ca32014-10-24 11:10:52 -07002067 private boolean isImsTurnOffAllowed() {
Brad Ebinger479f52c2017-08-28 13:19:22 -07002068 return isTurnOffImsAllowedByPlatform()
2069 && (!isWfcEnabledByPlatform()
2070 || !isWfcEnabledByUser());
Omkar Kolangade75f3ca32014-10-24 11:10:52 -07002071 }
2072
Amit Mahajan9cba36d2016-08-11 10:17:23 -07002073 private void setLteFeatureValues(boolean turnOn) {
2074 log("setLteFeatureValues: " + turnOn);
Brad Ebinger172977a2018-01-16 09:36:56 -08002075 CapabilityChangeRequest request = new CapabilityChangeRequest();
2076 if (turnOn) {
2077 request.addCapabilitiesToEnableForTech(
2078 MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE,
2079 ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
2080 } else {
2081 request.addCapabilitiesToDisableForTech(
2082 MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE,
2083 ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
2084 }
Pavel Zhamaitsiakff29b9d2016-04-15 12:16:57 -07002085
Brad Ebinger172977a2018-01-16 09:36:56 -08002086 if (isVolteEnabledByPlatform()) {
2087 boolean ignoreDataEnabledChanged = getBooleanCarrierConfig(
2088 CarrierConfigManager.KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS);
2089 boolean enableViLte = turnOn && isVtEnabledByUser() &&
2090 (ignoreDataEnabledChanged || isDataEnabled());
2091 if (enableViLte) {
2092 request.addCapabilitiesToEnableForTech(
2093 MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VIDEO,
2094 ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
2095 } else {
2096 request.addCapabilitiesToDisableForTech(
2097 MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VIDEO,
2098 ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
Etan Cohenb651fa52014-10-22 10:51:29 -07002099 }
Brad Ebinger172977a2018-01-16 09:36:56 -08002100 }
2101 try {
2102 mMmTelFeatureConnection.changeEnabledCapabilities(request, null);
2103 } catch (RemoteException e) {
2104 Log.e(TAG, "setLteFeatureValues: Exception: " + e.getMessage());
Etan Cohencfc784d2014-08-07 18:40:31 -07002105 }
Amit Mahajan9cba36d2016-08-11 10:17:23 -07002106 }
2107
2108 private void setAdvanced4GMode(boolean turnOn) throws ImsException {
2109 checkAndThrowExceptionIfServiceUnavailable();
2110
2111 // if turnOn: first set feature values then call turnOnIms()
2112 // if turnOff: only set feature values if IMS turn off is not allowed. If turn off is
2113 // allowed, first call turnOffIms() then set feature values
Etan Cohencfc784d2014-08-07 18:40:31 -07002114 if (turnOn) {
Amit Mahajan9cba36d2016-08-11 10:17:23 -07002115 setLteFeatureValues(turnOn);
2116 log("setAdvanced4GMode: turnOnIms");
Etan Cohencfc784d2014-08-07 18:40:31 -07002117 turnOnIms();
Amit Mahajan9cba36d2016-08-11 10:17:23 -07002118 } else {
2119 if (isImsTurnOffAllowed()) {
2120 log("setAdvanced4GMode: turnOffIms");
2121 turnOffIms();
2122 }
2123 setLteFeatureValues(turnOn);
Etan Cohencfc784d2014-08-07 18:40:31 -07002124 }
2125 }
2126
ram7da5a112014-07-16 20:59:27 +05302127 /**
2128 * Used for turning off IMS completely in order to make the device CSFB'ed.
2129 * Once turned off, all calls will be over CS.
2130 */
Etan Cohen82f78122014-12-15 10:10:14 -08002131 private void turnOffIms() throws ImsException {
Brad Ebinger172977a2018-01-16 09:36:56 -08002132 TelephonyManager tm = (TelephonyManager)
2133 mContext.getSystemService(Context.TELEPHONY_SERVICE);
2134 tm.disableIms(mPhoneId);
ram7da5a112014-07-16 20:59:27 +05302135 }
2136
Naveen Kalla525c3a22017-02-06 14:46:42 -08002137 private void addToRecentDisconnectReasons(ImsReasonInfo reason) {
2138 if (reason == null) return;
2139 while (mRecentDisconnectReasons.size() >= MAX_RECENT_DISCONNECT_REASONS) {
2140 mRecentDisconnectReasons.removeFirst();
2141 }
2142 mRecentDisconnectReasons.addLast(reason);
2143 }
2144
ram7da5a112014-07-16 20:59:27 +05302145 /**
Wink Savilleef36ef62014-06-11 08:39:38 -07002146 * Death recipient class for monitoring IMS service.
2147 */
2148 private class ImsServiceDeathRecipient implements IBinder.DeathRecipient {
2149 @Override
2150 public void binderDied() {
Brad Ebinger172977a2018-01-16 09:36:56 -08002151 mMmTelFeatureConnection = null;
Wink Savilleef36ef62014-06-11 08:39:38 -07002152 mUt = null;
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -05002153 mConfig = null;
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -07002154 mEcbm = null;
Tyler Gunn4d128b62016-04-13 15:44:38 -07002155 mMultiEndpoint = null;
Wink Savilleef36ef62014-06-11 08:39:38 -07002156 }
2157 }
2158
2159 /**
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -07002160 * Gets the ECBM interface to request ECBM exit.
2161 *
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -07002162 * @return the ECBM interface instance
2163 * @throws ImsException if getting the ECBM interface results in an error
2164 */
Brad Ebinger172977a2018-01-16 09:36:56 -08002165 public ImsEcbm getEcbmInterface() throws ImsException {
Brad Ebinger138b4a62017-06-20 16:29:50 -07002166 if (mEcbm != null && mEcbm.isBinderAlive()) {
2167 return mEcbm;
2168 }
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -07002169
Brad Ebinger138b4a62017-06-20 16:29:50 -07002170 checkAndThrowExceptionIfServiceUnavailable();
2171 try {
Brad Ebinger172977a2018-01-16 09:36:56 -08002172 IImsEcbm iEcbm = mMmTelFeatureConnection.getEcbmInterface();
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -07002173
Brad Ebinger138b4a62017-06-20 16:29:50 -07002174 if (iEcbm == null) {
2175 throw new ImsException("getEcbmInterface()",
2176 ImsReasonInfo.CODE_ECBM_NOT_SUPPORTED);
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -07002177 }
Brad Ebinger138b4a62017-06-20 16:29:50 -07002178 mEcbm = new ImsEcbm(iEcbm);
2179 } catch (RemoteException e) {
2180 throw new ImsException("getEcbmInterface()", e,
2181 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -07002182 }
2183 return mEcbm;
2184 }
Pavel Zhamaitsiak8c065f52015-11-10 14:36:44 -08002185
Mohamed Abdalkader4d68a982018-01-10 13:29:26 -08002186 public void sendSms(int token, int messageRef, String format, String smsc, boolean isRetry,
2187 byte[] pdu) throws ImsException {
2188 try {
Brad Ebinger172977a2018-01-16 09:36:56 -08002189 mMmTelFeatureConnection.sendSms(token, messageRef, format, smsc, isRetry, pdu);
Mohamed Abdalkader4d68a982018-01-10 13:29:26 -08002190 } catch (RemoteException e) {
2191 throw new ImsException("sendSms()", e, ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
2192 }
2193 }
2194
2195 public void acknowledgeSms(int token, int messageRef, int result) throws ImsException {
2196 try {
Brad Ebinger172977a2018-01-16 09:36:56 -08002197 mMmTelFeatureConnection.acknowledgeSms(token, messageRef, result);
Mohamed Abdalkader4d68a982018-01-10 13:29:26 -08002198 } catch (RemoteException e) {
2199 throw new ImsException("acknowledgeSms()", e,
2200 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
2201 }
2202 }
2203
2204 public void acknowledgeSmsReport(int token, int messageRef, int result) throws ImsException{
2205 try {
Brad Ebinger172977a2018-01-16 09:36:56 -08002206 mMmTelFeatureConnection.acknowledgeSmsReport(token, messageRef, result);
Mohamed Abdalkader4d68a982018-01-10 13:29:26 -08002207 } catch (RemoteException e) {
2208 throw new ImsException("acknowledgeSmsReport()", e,
2209 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
2210 }
2211 }
2212
2213 public String getSmsFormat() throws ImsException{
2214 try {
Brad Ebinger172977a2018-01-16 09:36:56 -08002215 return mMmTelFeatureConnection.getSmsFormat();
Mohamed Abdalkader4d68a982018-01-10 13:29:26 -08002216 } catch (RemoteException e) {
2217 throw new ImsException("getSmsFormat()", e,
2218 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
2219 }
2220 }
2221
2222 public void setSmsListener(IImsSmsListener listener) throws ImsException {
2223 try {
Brad Ebinger172977a2018-01-16 09:36:56 -08002224 mMmTelFeatureConnection.setSmsListener(listener);
Mohamed Abdalkader4d68a982018-01-10 13:29:26 -08002225 } catch (RemoteException e) {
2226 throw new ImsException("setSmsListener()", e,
2227 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
2228 }
2229 }
Mohamed Abdalkadere1453f42018-01-19 19:48:31 -08002230
Brad Ebingerd449b232018-02-12 14:33:05 -08002231 public void onSmsReady() throws ImsException {
Mohamed Abdalkader0e734e12018-01-23 13:11:00 -08002232 try {
Brad Ebinger190ed932018-01-23 13:41:32 -08002233 mMmTelFeatureConnection.onSmsReady();
Mohamed Abdalkader0e734e12018-01-23 13:11:00 -08002234 } catch (RemoteException e) {
2235 throw new ImsException("onSmsReady()", e,
2236 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
2237 }
2238 }
2239
Pavel Zhamaitsiak8c065f52015-11-10 14:36:44 -08002240 /**
Brad Ebingerd449b232018-02-12 14:33:05 -08002241 * Determines whether or not a call with the specified numbers should be placed over IMS or over
2242 * CSFB.
2243 * @param isEmergency is at least one call an emergency number.
2244 * @param numbers A {@link String} array containing the numbers in the call being placed. Can
2245 * be multiple numbers in the case of dialing out a conference.
2246 * @return The result of the query, one of the following values:
2247 * - {@link MmTelFeature#PROCESS_CALL_IMS}
2248 * - {@link MmTelFeature#PROCESS_CALL_CSFB}
2249 * @throws ImsException if the ImsService is not available. In this case, we should fall back
2250 * to CSFB anyway.
2251 */
2252 public @MmTelFeature.ProcessCallResult int shouldProcessCall(boolean isEmergency,
2253 String[] numbers) throws ImsException {
2254 try {
2255 return mMmTelFeatureConnection.shouldProcessCall(isEmergency, numbers);
2256 } catch (RemoteException e) {
2257 throw new ImsException("shouldProcessCall()", e,
2258 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
2259 }
2260 }
2261
2262 /**
Tyler Gunn4d128b62016-04-13 15:44:38 -07002263 * Gets the Multi-Endpoint interface to subscribe to multi-enpoint notifications..
2264 *
Tyler Gunn4d128b62016-04-13 15:44:38 -07002265 * @return the multi-endpoint interface instance
2266 * @throws ImsException if getting the multi-endpoint interface results in an error
2267 */
Brad Ebinger172977a2018-01-16 09:36:56 -08002268 public ImsMultiEndpoint getMultiEndpointInterface() throws ImsException {
Brad Ebinger138b4a62017-06-20 16:29:50 -07002269 if (mMultiEndpoint != null && mMultiEndpoint.isBinderAlive()) {
2270 return mMultiEndpoint;
Tyler Gunn4d128b62016-04-13 15:44:38 -07002271 }
Brad Ebinger138b4a62017-06-20 16:29:50 -07002272
2273 checkAndThrowExceptionIfServiceUnavailable();
2274 try {
Brad Ebinger172977a2018-01-16 09:36:56 -08002275 IImsMultiEndpoint iImsMultiEndpoint = mMmTelFeatureConnection.getMultiEndpointInterface();
Brad Ebinger138b4a62017-06-20 16:29:50 -07002276
2277 if (iImsMultiEndpoint == null) {
2278 throw new ImsException("getMultiEndpointInterface()",
2279 ImsReasonInfo.CODE_MULTIENDPOINT_NOT_SUPPORTED);
2280 }
2281 mMultiEndpoint = new ImsMultiEndpoint(iImsMultiEndpoint);
2282 } catch (RemoteException e) {
2283 throw new ImsException("getMultiEndpointInterface()", e,
2284 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
2285 }
2286
Tyler Gunn4d128b62016-04-13 15:44:38 -07002287 return mMultiEndpoint;
2288 }
2289
2290 /**
Pavel Zhamaitsiak8c065f52015-11-10 14:36:44 -08002291 * Resets ImsManager settings back to factory defaults.
2292 *
Brad Ebinger479f52c2017-08-28 13:19:22 -07002293 * @deprecated Doesn't support MSIM devices. Use {@link #factoryReset()} instead.
Brad Ebinger16417b42017-03-07 13:48:50 -08002294 *
Pavel Zhamaitsiak8c065f52015-11-10 14:36:44 -08002295 * @hide
2296 */
2297 public static void factoryReset(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -07002298 ImsManager mgr = ImsManager.getInstance(context,
2299 SubscriptionManager.getDefaultVoicePhoneId());
2300 if (mgr != null) {
2301 mgr.factoryReset();
2302 }
2303 loge("factoryReset: ImsManager null.");
Pavel Zhamaitsiak8c065f52015-11-10 14:36:44 -08002304 }
Jack Yu2f102bd2015-12-28 15:31:48 -08002305
Brad Ebinger16417b42017-03-07 13:48:50 -08002306 /**
2307 * Resets ImsManager settings back to factory defaults.
2308 *
2309 * @hide
2310 */
Brad Ebinger479f52c2017-08-28 13:19:22 -07002311 public void factoryReset() {
Brad Ebinger16417b42017-03-07 13:48:50 -08002312 // Set VoLTE to default
Malcolm Chen212ca652017-09-28 17:28:45 -07002313 SubscriptionManager.setSubscriptionProperty(getSubId(),
manabu, shimoda96aee542017-10-06 15:39:36 +09002314 SubscriptionManager.ENHANCED_4G_MODE_ENABLED,
2315 booleanToPropertyString(getBooleanCarrierConfig(
2316 CarrierConfigManager.KEY_ENHANCED_4G_LTE_ON_BY_DEFAULT_BOOL)));
Brad Ebinger16417b42017-03-07 13:48:50 -08002317
2318 // Set VoWiFi to default
Malcolm Chen212ca652017-09-28 17:28:45 -07002319 SubscriptionManager.setSubscriptionProperty(getSubId(),
2320 SubscriptionManager.WFC_IMS_ENABLED,
2321 booleanToPropertyString(getBooleanCarrierConfig(
2322 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ENABLED_BOOL)));
Brad Ebinger16417b42017-03-07 13:48:50 -08002323
2324 // Set VoWiFi mode to default
Malcolm Chen212ca652017-09-28 17:28:45 -07002325 SubscriptionManager.setSubscriptionProperty(getSubId(),
2326 SubscriptionManager.WFC_IMS_MODE,
2327 Integer.toString(getIntCarrierConfig(
2328 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_MODE_INT)));
Brad Ebinger16417b42017-03-07 13:48:50 -08002329
2330 // Set VoWiFi roaming to default
Malcolm Chen212ca652017-09-28 17:28:45 -07002331 SubscriptionManager.setSubscriptionProperty(getSubId(),
2332 SubscriptionManager.WFC_IMS_ROAMING_ENABLED,
2333 booleanToPropertyString(getBooleanCarrierConfig(
2334 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_ENABLED_BOOL)));
Brad Ebinger16417b42017-03-07 13:48:50 -08002335
2336 // Set VT to default
Malcolm Chen212ca652017-09-28 17:28:45 -07002337 SubscriptionManager.setSubscriptionProperty(getSubId(),
2338 SubscriptionManager.VT_IMS_ENABLED, booleanToPropertyString(true));
Brad Ebinger16417b42017-03-07 13:48:50 -08002339
2340 // Push settings to ImsConfig
Brad Ebinger479f52c2017-08-28 13:19:22 -07002341 updateImsServiceConfig(true);
Brad Ebinger16417b42017-03-07 13:48:50 -08002342 }
2343
Amit Mahajan24f7b162016-07-21 16:33:53 -07002344 private boolean isDataEnabled() {
Malcolm Chend0ef12c2017-12-20 11:38:25 -08002345 return new TelephonyManager(mContext, getSubId()).isMobileDataEnabled();
Amit Mahajan24f7b162016-07-21 16:33:53 -07002346 }
2347
2348 private boolean isVolteProvisioned() {
Malcolm Chen18837ff2017-10-25 17:05:41 -07002349 return getProvisionedBoolNoException(
2350 ImsConfig.ConfigConstants.VLT_SETTING_ENABLED);
Amit Mahajan24f7b162016-07-21 16:33:53 -07002351 }
2352
2353 private boolean isWfcProvisioned() {
Malcolm Chen18837ff2017-10-25 17:05:41 -07002354 return getProvisionedBoolNoException(
2355 ImsConfig.ConfigConstants.VOICE_OVER_WIFI_SETTING_ENABLED);
Amit Mahajan24f7b162016-07-21 16:33:53 -07002356 }
2357
2358 private boolean isVtProvisioned() {
Malcolm Chen18837ff2017-10-25 17:05:41 -07002359 return getProvisionedBoolNoException(
2360 ImsConfig.ConfigConstants.LVC_SETTING_ENABLED);
Jack Yu643ffe42016-07-08 14:25:46 -07002361 }
2362
Malcolm Chen212ca652017-09-28 17:28:45 -07002363 private static String booleanToPropertyString(boolean bool) {
2364 return bool ? "1" : "0";
2365 }
2366
2367
Jack Yu2f102bd2015-12-28 15:31:48 -08002368 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
2369 pw.println("ImsManager:");
2370 pw.println(" mPhoneId = " + mPhoneId);
2371 pw.println(" mConfigUpdated = " + mConfigUpdated);
Brad Ebinger172977a2018-01-16 09:36:56 -08002372 pw.println(" mImsServiceProxy = " + mMmTelFeatureConnection);
Amit Mahajan24f7b162016-07-21 16:33:53 -07002373 pw.println(" mDataEnabled = " + isDataEnabled());
Brad Ebinger479f52c2017-08-28 13:19:22 -07002374 pw.println(" ignoreDataEnabledChanged = " + getBooleanCarrierConfig(
Jack Yu57781852016-11-16 17:20:38 -08002375 CarrierConfigManager.KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS));
Jack Yu2f102bd2015-12-28 15:31:48 -08002376
Brad Ebinger479f52c2017-08-28 13:19:22 -07002377 pw.println(" isGbaValid = " + isGbaValid());
Jack Yu2f102bd2015-12-28 15:31:48 -08002378 pw.println(" isImsTurnOffAllowed = " + isImsTurnOffAllowed());
Brad Ebinger479f52c2017-08-28 13:19:22 -07002379 pw.println(" isNonTtyOrTtyOnVolteEnabled = " + isNonTtyOrTtyOnVolteEnabled());
Jack Yu2f102bd2015-12-28 15:31:48 -08002380
Brad Ebinger479f52c2017-08-28 13:19:22 -07002381 pw.println(" isVolteEnabledByPlatform = " + isVolteEnabledByPlatform());
2382 pw.println(" isVolteProvisionedOnDevice = " + isVolteProvisionedOnDevice());
Jack Yu2f102bd2015-12-28 15:31:48 -08002383 pw.println(" isEnhanced4gLteModeSettingEnabledByUser = " +
Brad Ebinger479f52c2017-08-28 13:19:22 -07002384 isEnhanced4gLteModeSettingEnabledByUser());
2385 pw.println(" isVtEnabledByPlatform = " + isVtEnabledByPlatform());
2386 pw.println(" isVtEnabledByUser = " + isVtEnabledByUser());
Jack Yu2f102bd2015-12-28 15:31:48 -08002387
Brad Ebinger479f52c2017-08-28 13:19:22 -07002388 pw.println(" isWfcEnabledByPlatform = " + isWfcEnabledByPlatform());
2389 pw.println(" isWfcEnabledByUser = " + isWfcEnabledByUser());
2390 pw.println(" getWfcMode = " + getWfcMode());
2391 pw.println(" isWfcRoamingEnabledByUser = " + isWfcRoamingEnabledByUser());
Jack Yu2f102bd2015-12-28 15:31:48 -08002392
Brad Ebinger479f52c2017-08-28 13:19:22 -07002393 pw.println(" isVtProvisionedOnDevice = " + isVtProvisionedOnDevice());
2394 pw.println(" isWfcProvisionedOnDevice = " + isWfcProvisionedOnDevice());
Jack Yu2f102bd2015-12-28 15:31:48 -08002395 pw.flush();
2396 }
Wink Savilleef36ef62014-06-11 08:39:38 -07002397}