blob: 8ae97c81fe934df872544581f303aceb4f68573a [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) {
Brad Ebinger6ddf28e2018-02-21 16:07:23 -0800342 manager = mImsManager;
343 }
Brad Ebinger0aed76d2018-03-05 16:39:02 -0800344 try {
345 mListener.connectionReady(manager);
346 }
347 catch (ImsException e) {
348 Log.w(TAG, "Connector: notifyReady exception: " + e.getMessage());
349 throw e;
350 }
351 // Only reset retry count if connectionReady does not generate an ImsException/
352 synchronized (mLock) {
353 mRetryCount = 0;
354 }
Brad Ebinger6ddf28e2018-02-21 16:07:23 -0800355 }
356
357 private void notifyNotReady() {
358 mListener.connectionUnavailable();
359 }
360 }
361
Wink Saville1e5a38a2014-10-23 10:24:46 -0700362 private static HashMap<Integer, ImsManager> sImsManagerInstances =
363 new HashMap<Integer, ImsManager>();
Etan Cohend7727462014-07-12 14:54:10 -0700364
Wink Savilleef36ef62014-06-11 08:39:38 -0700365 private Context mContext;
Brad Ebinger16417b42017-03-07 13:48:50 -0800366 private CarrierConfigManager mConfigManager;
Etan Cohenabbd7882014-09-26 22:35:35 -0700367 private int mPhoneId;
Brad Ebinger16780ff2017-01-26 11:18:21 -0800368 private final boolean mConfigDynamicBind;
Brad Ebinger172977a2018-01-16 09:36:56 -0800369 private @Nullable MmTelFeatureConnection mMmTelFeatureConnection = null;
Wink Savilleef36ef62014-06-11 08:39:38 -0700370 private ImsServiceDeathRecipient mDeathRecipient = new ImsServiceDeathRecipient();
371 // Ut interface for the supplementary service configuration
372 private ImsUt mUt = null;
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -0500373 // Interface to get/set ims config items
374 private ImsConfig mConfig = null;
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -0700375 private boolean mConfigUpdated = false;
Wink Savilleef36ef62014-06-11 08:39:38 -0700376
Pavel Zhamaitsiakf4b90322016-01-26 14:34:09 -0800377 private ImsConfigListener mImsConfigListener;
378
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -0700379 // ECBM interface
380 private ImsEcbm mEcbm = null;
381
Tyler Gunn4d128b62016-04-13 15:44:38 -0700382 private ImsMultiEndpoint mMultiEndpoint = null;
383
Brad Ebinger172977a2018-01-16 09:36:56 -0800384 private Set<MmTelFeatureConnection.IFeatureUpdate> mStatusCallbacks =
385 new CopyOnWriteArraySet<>();
Brad Ebinger16780ff2017-01-26 11:18:21 -0800386
Amit Mahajan24f7b162016-07-21 16:33:53 -0700387 public static final String TRUE = "true";
388 public static final String FALSE = "false";
Jack Yu643ffe42016-07-08 14:25:46 -0700389
Naveen Kalla525c3a22017-02-06 14:46:42 -0800390 // mRecentDisconnectReasons stores the last 16 disconnect reasons
391 private static final int MAX_RECENT_DISCONNECT_REASONS = 16;
392 private ConcurrentLinkedDeque<ImsReasonInfo> mRecentDisconnectReasons =
393 new ConcurrentLinkedDeque<>();
394
Wink Savilleef36ef62014-06-11 08:39:38 -0700395 /**
396 * Gets a manager instance.
397 *
398 * @param context application context for creating the manager object
Etan Cohenabbd7882014-09-26 22:35:35 -0700399 * @param phoneId the phone ID for the IMS Service
400 * @return the manager instance corresponding to the phoneId
Wink Savilleef36ef62014-06-11 08:39:38 -0700401 */
Etan Cohenabbd7882014-09-26 22:35:35 -0700402 public static ImsManager getInstance(Context context, int phoneId) {
Etan Cohend7727462014-07-12 14:54:10 -0700403 synchronized (sImsManagerInstances) {
Naveen Kalla525c3a22017-02-06 14:46:42 -0800404 if (sImsManagerInstances.containsKey(phoneId)) {
Brad Ebingerff097922017-06-19 15:43:08 -0700405 ImsManager m = sImsManagerInstances.get(phoneId);
406 // May be null for some tests
407 if (m != null) {
408 m.connectIfServiceIsAvailable();
409 }
410 return m;
Naveen Kalla525c3a22017-02-06 14:46:42 -0800411 }
Wink Savilleef36ef62014-06-11 08:39:38 -0700412
Etan Cohenabbd7882014-09-26 22:35:35 -0700413 ImsManager mgr = new ImsManager(context, phoneId);
414 sImsManagerInstances.put(phoneId, mgr);
Etan Cohend7727462014-07-12 14:54:10 -0700415
416 return mgr;
417 }
Wink Savilleef36ef62014-06-11 08:39:38 -0700418 }
419
Etan Cohen45b5f312014-08-19 15:55:08 -0700420 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800421 * Returns the user configuration of Enhanced 4G LTE Mode setting.
422 *
423 * @deprecated Doesn't support MSIM devices. Use
Brad Ebinger479f52c2017-08-28 13:19:22 -0700424 * {@link #isEnhanced4gLteModeSettingEnabledByUser()} instead.
Etan Cohen45b5f312014-08-19 15:55:08 -0700425 */
426 public static boolean isEnhanced4gLteModeSettingEnabledByUser(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700427 ImsManager mgr = ImsManager.getInstance(context,
428 SubscriptionManager.getDefaultVoicePhoneId());
429 if (mgr != null) {
430 return mgr.isEnhanced4gLteModeSettingEnabledByUser();
Sungmin Choi2f1af952016-02-01 17:15:35 +0900431 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700432 loge("isEnhanced4gLteModeSettingEnabledByUser: ImsManager null, returning default value.");
433 return false;
Etan Cohen45b5f312014-08-19 15:55:08 -0700434 }
435
436 /**
manabu, shimoda96aee542017-10-06 15:39:36 +0900437 * Returns the user configuration of Enhanced 4G LTE Mode setting for slot. If the option is
438 * not editable ({@link CarrierConfigManager#KEY_EDITABLE_ENHANCED_4G_LTE_BOOL} is false), or
439 * the setting is not initialized, this method will return default value specified by
440 * {@link CarrierConfigManager#KEY_ENHANCED_4G_LTE_ON_BY_DEFAULT_BOOL}.
441 *
442 * Note that even if the setting was set, it may no longer be editable. If this is the case we
443 * return the default value.
Brad Ebinger16417b42017-03-07 13:48:50 -0800444 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700445 public boolean isEnhanced4gLteModeSettingEnabledByUser() {
Malcolm Chen212ca652017-09-28 17:28:45 -0700446 int setting = SubscriptionManager.getIntegerSubscriptionProperty(
447 getSubId(), SubscriptionManager.ENHANCED_4G_MODE_ENABLED,
448 SUB_PROPERTY_NOT_INITIALIZED, mContext);
manabu, shimoda96aee542017-10-06 15:39:36 +0900449 boolean onByDefault = getBooleanCarrierConfig(
450 CarrierConfigManager.KEY_ENHANCED_4G_LTE_ON_BY_DEFAULT_BOOL);
Malcolm Chen212ca652017-09-28 17:28:45 -0700451
manabu, shimoda96aee542017-10-06 15:39:36 +0900452 // If Enhanced 4G LTE Mode is uneditable or not initialized, we use the default value
453 if (!getBooleanCarrierConfig(CarrierConfigManager.KEY_EDITABLE_ENHANCED_4G_LTE_BOOL)
454 || setting == SUB_PROPERTY_NOT_INITIALIZED) {
455 return onByDefault;
456 } else {
457 return (setting == ImsConfig.FeatureValueConstants.ON);
458 }
Brad Ebinger16417b42017-03-07 13:48:50 -0800459 }
460
461 /**
462 * Change persistent Enhanced 4G LTE Mode setting.
463 *
Brad Ebinger479f52c2017-08-28 13:19:22 -0700464 * @deprecated Doesn't support MSIM devices. Use {@link #setEnhanced4gLteModeSetting(boolean)}
Brad Ebinger16417b42017-03-07 13:48:50 -0800465 * instead.
Etan Cohen82f78122014-12-15 10:10:14 -0800466 */
467 public static void setEnhanced4gLteModeSetting(Context context, boolean enabled) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700468 ImsManager mgr = ImsManager.getInstance(context,
469 SubscriptionManager.getDefaultVoicePhoneId());
470 if (mgr != null) {
471 mgr.setEnhanced4gLteModeSetting(enabled);
Etan Cohen82f78122014-12-15 10:10:14 -0800472 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700473 loge("setEnhanced4gLteModeSetting: ImsManager null, value not set.");
Etan Cohen82f78122014-12-15 10:10:14 -0800474 }
475
476 /**
manabu, shimoda96aee542017-10-06 15:39:36 +0900477 * Change persistent Enhanced 4G LTE Mode setting. If the option is not editable
Brad Ebinger16417b42017-03-07 13:48:50 -0800478 * ({@link CarrierConfigManager#KEY_EDITABLE_ENHANCED_4G_LTE_BOOL} is false), this method will
manabu, shimoda96aee542017-10-06 15:39:36 +0900479 * set the setting to the default value specified by
480 * {@link CarrierConfigManager#KEY_ENHANCED_4G_LTE_ON_BY_DEFAULT_BOOL}.
Brad Ebinger16417b42017-03-07 13:48:50 -0800481 *
482 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700483 public void setEnhanced4gLteModeSetting(boolean enabled) {
manabu, shimoda96aee542017-10-06 15:39:36 +0900484 // If editable=false, we must keep default advanced 4G mode.
485 if (!getBooleanCarrierConfig(CarrierConfigManager.KEY_EDITABLE_ENHANCED_4G_LTE_BOOL)) {
486 enabled = getBooleanCarrierConfig(
487 CarrierConfigManager.KEY_ENHANCED_4G_LTE_ON_BY_DEFAULT_BOOL);
488 }
Brad Ebinger16417b42017-03-07 13:48:50 -0800489
Malcolm Chen212ca652017-09-28 17:28:45 -0700490 int prevSetting = SubscriptionManager.getIntegerSubscriptionProperty(
491 getSubId(), SubscriptionManager.ENHANCED_4G_MODE_ENABLED,
492 SUB_PROPERTY_NOT_INITIALIZED, mContext);
Brad Ebinger16417b42017-03-07 13:48:50 -0800493
manabu, shimoda96aee542017-10-06 15:39:36 +0900494 if (prevSetting != (enabled ?
495 ImsConfig.FeatureValueConstants.ON :
496 ImsConfig.FeatureValueConstants.OFF)) {
Malcolm Chen212ca652017-09-28 17:28:45 -0700497 SubscriptionManager.setSubscriptionProperty(getSubId(),
498 SubscriptionManager.ENHANCED_4G_MODE_ENABLED, booleanToPropertyString(enabled));
499 if (isNonTtyOrTtyOnVolteEnabled()) {
500 try {
501 setAdvanced4GMode(enabled);
502 } catch (ImsException ie) {
503 // do nothing
504 }
Brad Ebinger16417b42017-03-07 13:48:50 -0800505 }
506 }
507 }
508
509 /**
Etan Cohen82f78122014-12-15 10:10:14 -0800510 * Indicates whether the call is non-TTY or if TTY - whether TTY on VoLTE is
511 * supported.
Brad Ebinger16417b42017-03-07 13:48:50 -0800512 * @deprecated Does not support MSIM devices. Please use
Brad Ebinger479f52c2017-08-28 13:19:22 -0700513 * {@link #isNonTtyOrTtyOnVolteEnabled()} instead.
Etan Cohen82f78122014-12-15 10:10:14 -0800514 */
515 public static boolean isNonTtyOrTtyOnVolteEnabled(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700516 ImsManager mgr = ImsManager.getInstance(context,
517 SubscriptionManager.getDefaultVoicePhoneId());
518 if (mgr != null) {
519 return mgr.isNonTtyOrTtyOnVolteEnabled();
520 }
521 loge("isNonTtyOrTtyOnVolteEnabled: ImsManager null, returning default value.");
522 return false;
523 }
524
525 /**
526 * Indicates whether the call is non-TTY or if TTY - whether TTY on VoLTE is
527 * supported on a per slot basis.
528 */
529 public boolean isNonTtyOrTtyOnVolteEnabled() {
530 if (getBooleanCarrierConfig(
fionaxu5803ef02016-03-08 11:48:48 -0800531 CarrierConfigManager.KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL)) {
Etan Cohen82f78122014-12-15 10:10:14 -0800532 return true;
533 }
534
Brad Ebinger479f52c2017-08-28 13:19:22 -0700535 TelecomManager tm = (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
Hall Liue511a202017-08-17 15:49:58 -0700536 if (tm == null) {
537 Log.w(TAG, "isNonTtyOrTtyOnVolteEnabled: telecom not available");
538 return true;
539 }
540 return tm.getCurrentTtyMode() == TelecomManager.TTY_MODE_OFF;
Etan Cohen82f78122014-12-15 10:10:14 -0800541 }
542
543 /**
Etan Cohenea2b5832014-10-23 18:50:35 -0700544 * Returns a platform configuration for VoLTE which may override the user setting.
Brad Ebinger16417b42017-03-07 13:48:50 -0800545 * @deprecated Does not support MSIM devices. Please use
Brad Ebinger479f52c2017-08-28 13:19:22 -0700546 * {@link #isVolteEnabledByPlatform()} instead.
Etan Cohen45b5f312014-08-19 15:55:08 -0700547 */
Etan Cohenea2b5832014-10-23 18:50:35 -0700548 public static boolean isVolteEnabledByPlatform(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700549 ImsManager mgr = ImsManager.getInstance(context,
550 SubscriptionManager.getDefaultVoicePhoneId());
551 if (mgr != null) {
552 return mgr.isVolteEnabledByPlatform();
Etan Cohenaf55a402014-09-04 22:34:41 -0700553 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700554 loge("isVolteEnabledByPlatform: ImsManager null, returning default value.");
555 return false;
Etan Cohenb5388a32014-11-26 11:57:47 -0800556 }
557
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700558 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800559 * Returns a platform configuration for VoLTE which may override the user setting on a per Slot
560 * basis.
561 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700562 public boolean isVolteEnabledByPlatform() {
Malcolm Chen18837ff2017-10-25 17:05:41 -0700563 // We first read the per slot value. If doesn't exist, we read the general value. If still
564 // doesn't exist, we use the hardcoded default value.
565 if (SystemProperties.getInt(
566 PROPERTY_DBG_VOLTE_AVAIL_OVERRIDE + Integer.toString(mPhoneId),
567 SYSTEM_PROPERTY_NOT_SET) == 1 ||
568 SystemProperties.getInt(PROPERTY_DBG_VOLTE_AVAIL_OVERRIDE,
569 SYSTEM_PROPERTY_NOT_SET) == 1) {
Brad Ebinger16417b42017-03-07 13:48:50 -0800570 return true;
571 }
572
573 return mContext.getResources().getBoolean(
574 com.android.internal.R.bool.config_device_volte_available)
Malcolm Chen212ca652017-09-28 17:28:45 -0700575 && getBooleanCarrierConfig(CarrierConfigManager.KEY_CARRIER_VOLTE_AVAILABLE_BOOL)
Brad Ebinger479f52c2017-08-28 13:19:22 -0700576 && isGbaValid();
Brad Ebinger16417b42017-03-07 13:48:50 -0800577 }
578
579 /**
580 * Indicates whether VoLTE is provisioned on device.
581 *
582 * @deprecated Does not support MSIM devices. Please use
Brad Ebinger479f52c2017-08-28 13:19:22 -0700583 * {@link #isVolteProvisionedOnDevice()} instead.
Etan Cohenb5388a32014-11-26 11:57:47 -0800584 */
585 public static boolean isVolteProvisionedOnDevice(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700586 ImsManager mgr = ImsManager.getInstance(context,
587 SubscriptionManager.getDefaultVoicePhoneId());
588 if (mgr != null) {
589 return mgr.isVolteProvisionedOnDevice();
Etan Cohenb5388a32014-11-26 11:57:47 -0800590 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700591 loge("isVolteProvisionedOnDevice: ImsManager null, returning default value.");
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700592 return true;
593 }
594
595 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800596 * Indicates whether VoLTE is provisioned on this slot.
597 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700598 public boolean isVolteProvisionedOnDevice() {
599 if (getBooleanCarrierConfig(
Brad Ebinger16417b42017-03-07 13:48:50 -0800600 CarrierConfigManager.KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL)) {
601 return isVolteProvisioned();
602 }
603
604 return true;
605 }
606
607 /**
Meng Wang54fd41a2017-04-12 11:44:47 -0700608 * Indicates whether VoWifi is provisioned on device.
609 *
610 * When CarrierConfig KEY_CARRIER_VOLTE_OVERRIDE_WFC_PROVISIONING_BOOL is true, and VoLTE is not
611 * provisioned on device, this method returns false.
Brad Ebinger16417b42017-03-07 13:48:50 -0800612 *
613 * @deprecated Does not support MSIM devices. Please use
Brad Ebinger479f52c2017-08-28 13:19:22 -0700614 * {@link #isWfcProvisionedOnDevice()} instead.
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700615 */
616 public static boolean isWfcProvisionedOnDevice(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700617 ImsManager mgr = ImsManager.getInstance(context,
618 SubscriptionManager.getDefaultVoicePhoneId());
619 if (mgr != null) {
620 return mgr.isWfcProvisionedOnDevice();
Meng Wang54fd41a2017-04-12 11:44:47 -0700621 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700622 loge("isWfcProvisionedOnDevice: ImsManager null, returning default value.");
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700623 return true;
624 }
625
626 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800627 * Indicates whether VoWifi is provisioned on slot.
Meng Wang54fd41a2017-04-12 11:44:47 -0700628 *
629 * When CarrierConfig KEY_CARRIER_VOLTE_OVERRIDE_WFC_PROVISIONING_BOOL is true, and VoLTE is not
630 * provisioned on device, this method returns false.
Brad Ebinger16417b42017-03-07 13:48:50 -0800631 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700632 public boolean isWfcProvisionedOnDevice() {
633 if (getBooleanCarrierConfig(
Meng Wang54fd41a2017-04-12 11:44:47 -0700634 CarrierConfigManager.KEY_CARRIER_VOLTE_OVERRIDE_WFC_PROVISIONING_BOOL)) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700635 if (!isVolteProvisionedOnDevice()) {
Meng Wang54fd41a2017-04-12 11:44:47 -0700636 return false;
637 }
638 }
639
Brad Ebinger479f52c2017-08-28 13:19:22 -0700640 if (getBooleanCarrierConfig(
Brad Ebinger16417b42017-03-07 13:48:50 -0800641 CarrierConfigManager.KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL)) {
Meng Wang54fd41a2017-04-12 11:44:47 -0700642 return isWfcProvisioned();
Brad Ebinger16417b42017-03-07 13:48:50 -0800643 }
644
645 return true;
646 }
647
648 /**
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700649 * Indicates whether VT is provisioned on device
Brad Ebinger16417b42017-03-07 13:48:50 -0800650 *
651 * @deprecated Does not support MSIM devices. Please use
Brad Ebinger479f52c2017-08-28 13:19:22 -0700652 * {@link #isVtProvisionedOnDevice()} instead.
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700653 */
654 public static boolean isVtProvisionedOnDevice(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700655 ImsManager mgr = ImsManager.getInstance(context,
656 SubscriptionManager.getDefaultVoicePhoneId());
657 if (mgr != null) {
658 return mgr.isVtProvisionedOnDevice();
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700659 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700660 loge("isVtProvisionedOnDevice: ImsManager null, returning default value.");
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700661 return true;
Etan Cohenb651fa52014-10-22 10:51:29 -0700662 }
663
Etan Cohenea2b5832014-10-23 18:50:35 -0700664 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800665 * Indicates whether VT is provisioned on slot.
666 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700667 public boolean isVtProvisionedOnDevice() {
668 if (getBooleanCarrierConfig(
Brad Ebinger16417b42017-03-07 13:48:50 -0800669 CarrierConfigManager.KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL)) {
670 return isVtProvisioned();
671 }
672
673 return true;
674 }
675
676 /**
Etan Cohenea2b5832014-10-23 18:50:35 -0700677 * Returns a platform configuration for VT which may override the user setting.
678 *
679 * Note: VT presumes that VoLTE is enabled (these are configuration settings
680 * which must be done correctly).
Brad Ebinger16417b42017-03-07 13:48:50 -0800681 *
682 * @deprecated Does not support MSIM devices. Please use
Brad Ebinger479f52c2017-08-28 13:19:22 -0700683 * {@link #isVtEnabledByPlatform()} instead.
Etan Cohenea2b5832014-10-23 18:50:35 -0700684 */
Etan Cohenb651fa52014-10-22 10:51:29 -0700685 public static boolean isVtEnabledByPlatform(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700686 ImsManager mgr = ImsManager.getInstance(context,
687 SubscriptionManager.getDefaultVoicePhoneId());
688 if (mgr != null) {
689 return mgr.isVtEnabledByPlatform();
Etan Cohenea2b5832014-10-23 18:50:35 -0700690 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700691 loge("isVtEnabledByPlatform: ImsManager null, returning default value.");
692 return false;
Etan Cohen45b5f312014-08-19 15:55:08 -0700693 }
694
Etan Cohena00c9192014-12-23 15:02:29 -0800695 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800696 * Returns a platform configuration for VT which may override the user setting.
697 *
698 * Note: VT presumes that VoLTE is enabled (these are configuration settings
699 * which must be done correctly).
700 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700701 public boolean isVtEnabledByPlatform() {
Malcolm Chen18837ff2017-10-25 17:05:41 -0700702 // We first read the per slot value. If doesn't exist, we read the general value. If still
703 // doesn't exist, we use the hardcoded default value.
704 if (SystemProperties.getInt(PROPERTY_DBG_VT_AVAIL_OVERRIDE +
705 Integer.toString(mPhoneId), SYSTEM_PROPERTY_NOT_SET) == 1 ||
706 SystemProperties.getInt(
707 PROPERTY_DBG_VT_AVAIL_OVERRIDE, SYSTEM_PROPERTY_NOT_SET) == 1) {
Brad Ebinger16417b42017-03-07 13:48:50 -0800708 return true;
709 }
710
711 return mContext.getResources().getBoolean(
712 com.android.internal.R.bool.config_device_vt_available) &&
Malcolm Chen212ca652017-09-28 17:28:45 -0700713 getBooleanCarrierConfig(CarrierConfigManager.KEY_CARRIER_VT_AVAILABLE_BOOL) &&
Brad Ebinger479f52c2017-08-28 13:19:22 -0700714 isGbaValid();
Brad Ebinger16417b42017-03-07 13:48:50 -0800715 }
716
717 /**
Etan Cohena7d32e82015-05-04 18:02:09 -0700718 * Returns the user configuration of VT setting
Brad Ebinger16417b42017-03-07 13:48:50 -0800719 * @deprecated Does not support MSIM devices. Please use
Brad Ebinger479f52c2017-08-28 13:19:22 -0700720 * {@link #isVtEnabledByUser()} instead.
Etan Cohena7d32e82015-05-04 18:02:09 -0700721 */
722 public static boolean isVtEnabledByUser(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700723 ImsManager mgr = ImsManager.getInstance(context,
724 SubscriptionManager.getDefaultVoicePhoneId());
725 if (mgr != null) {
726 return mgr.isVtEnabledByUser();
727 }
728 loge("isVtEnabledByUser: ImsManager null, returning default value.");
729 return false;
Etan Cohena7d32e82015-05-04 18:02:09 -0700730 }
731
732 /**
Malcolm Chen212ca652017-09-28 17:28:45 -0700733 * Returns the user configuration of VT setting per slot. If not set, it
734 * returns true as default value.
Brad Ebinger16417b42017-03-07 13:48:50 -0800735 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700736 public boolean isVtEnabledByUser() {
Malcolm Chen212ca652017-09-28 17:28:45 -0700737 int setting = SubscriptionManager.getIntegerSubscriptionProperty(
738 getSubId(), SubscriptionManager.VT_IMS_ENABLED,
739 SUB_PROPERTY_NOT_INITIALIZED, mContext);
740
741 // If it's never set, by default we return true.
manabu, shimoda96aee542017-10-06 15:39:36 +0900742 return (setting == SUB_PROPERTY_NOT_INITIALIZED
743 || setting == ImsConfig.FeatureValueConstants.ON);
Brad Ebinger16417b42017-03-07 13:48:50 -0800744 }
745
746 /**
Etan Cohena7d32e82015-05-04 18:02:09 -0700747 * Change persistent VT enabled setting
Brad Ebinger16417b42017-03-07 13:48:50 -0800748 *
Brad Ebinger479f52c2017-08-28 13:19:22 -0700749 * @deprecated Does not support MSIM devices. Please use {@link #setVtSetting(boolean)} instead.
Etan Cohena7d32e82015-05-04 18:02:09 -0700750 */
751 public static void setVtSetting(Context context, boolean enabled) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700752 ImsManager mgr = ImsManager.getInstance(context,
Etan Cohena7d32e82015-05-04 18:02:09 -0700753 SubscriptionManager.getDefaultVoicePhoneId());
Brad Ebinger479f52c2017-08-28 13:19:22 -0700754 if (mgr != null) {
755 mgr.setVtSetting(enabled);
Etan Cohena7d32e82015-05-04 18:02:09 -0700756 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700757 loge("setVtSetting: ImsManager null, can not set value.");
Etan Cohena7d32e82015-05-04 18:02:09 -0700758 }
759
Brad Ebinger16417b42017-03-07 13:48:50 -0800760 /**
761 * Change persistent VT enabled setting for slot.
762 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700763 public void setVtSetting(boolean enabled) {
Brad Ebinger172977a2018-01-16 09:36:56 -0800764 SubscriptionManager.setSubscriptionProperty(getSubId(), SubscriptionManager.VT_IMS_ENABLED,
Malcolm Chen212ca652017-09-28 17:28:45 -0700765 booleanToPropertyString(enabled));
Brad Ebinger172977a2018-01-16 09:36:56 -0800766
Brad Ebinger16417b42017-03-07 13:48:50 -0800767 try {
Brad Ebinger172977a2018-01-16 09:36:56 -0800768 changeMmTelCapability(MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VIDEO,
769 ImsRegistrationImplBase.REGISTRATION_TECH_LTE, enabled);
Brad Ebinger16417b42017-03-07 13:48:50 -0800770
771 if (enabled) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700772 log("setVtSetting(b) : turnOnIms");
Brad Ebinger16417b42017-03-07 13:48:50 -0800773 turnOnIms();
Brad Ebinger2384f422018-03-15 16:09:41 -0700774 } else if (isTurnOffImsAllowedByPlatform()
Brad Ebinger479f52c2017-08-28 13:19:22 -0700775 && (!isVolteEnabledByPlatform()
776 || !isEnhanced4gLteModeSettingEnabledByUser())) {
777 log("setVtSetting(b) : imsServiceAllowTurnOff -> turnOffIms");
Brad Ebinger16417b42017-03-07 13:48:50 -0800778 turnOffIms();
779 }
Brad Ebinger172977a2018-01-16 09:36:56 -0800780 } catch (ImsException | RemoteException e) {
781 // The ImsService is down. Since the SubscriptionManager already recorded the user's
782 // preference, it will be resent in updateImsServiceConfig when the ImsPhoneCallTracker
783 // reconnects.
Brad Ebinger479f52c2017-08-28 13:19:22 -0700784 loge("setVtSetting(b): ", e);
Brad Ebinger16417b42017-03-07 13:48:50 -0800785 }
786 }
787
788 /**
Meng Wang9352c432016-06-08 14:22:20 -0700789 * Returns whether turning off ims is allowed by platform.
790 * The platform property may override the carrier config.
Brad Ebinger16417b42017-03-07 13:48:50 -0800791 *
792 * @deprecated Does not support MSIM devices. Please use
Brad Ebinger479f52c2017-08-28 13:19:22 -0700793 * {@link #isTurnOffImsAllowedByPlatform()} instead.
Meng Wang9352c432016-06-08 14:22:20 -0700794 */
795 private static boolean isTurnOffImsAllowedByPlatform(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700796 ImsManager mgr = ImsManager.getInstance(context,
797 SubscriptionManager.getDefaultVoicePhoneId());
798 if (mgr != null) {
799 return mgr.isTurnOffImsAllowedByPlatform();
Meng Wang9352c432016-06-08 14:22:20 -0700800 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700801 loge("isTurnOffImsAllowedByPlatform: ImsManager null, returning default value.");
802 return true;
Meng Wang9352c432016-06-08 14:22:20 -0700803 }
804
Etan Cohena7d32e82015-05-04 18:02:09 -0700805 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800806 * Returns whether turning off ims is allowed by platform.
807 * The platform property may override the carrier config.
808 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700809 private boolean isTurnOffImsAllowedByPlatform() {
Malcolm Chen18837ff2017-10-25 17:05:41 -0700810 // We first read the per slot value. If doesn't exist, we read the general value. If still
811 // doesn't exist, we use the hardcoded default value.
812 if (SystemProperties.getInt(PROPERTY_DBG_ALLOW_IMS_OFF_OVERRIDE +
813 Integer.toString(mPhoneId), SYSTEM_PROPERTY_NOT_SET) == 1 ||
814 SystemProperties.getInt(
815 PROPERTY_DBG_ALLOW_IMS_OFF_OVERRIDE, SYSTEM_PROPERTY_NOT_SET) == 1) {
Brad Ebinger16417b42017-03-07 13:48:50 -0800816 return true;
817 }
Malcolm Chen18837ff2017-10-25 17:05:41 -0700818
Brad Ebinger479f52c2017-08-28 13:19:22 -0700819 return getBooleanCarrierConfig(
Brad Ebinger16417b42017-03-07 13:48:50 -0800820 CarrierConfigManager.KEY_CARRIER_ALLOW_TURNOFF_IMS_BOOL);
821 }
822
823 /**
Etan Cohena00c9192014-12-23 15:02:29 -0800824 * Returns the user configuration of WFC setting
Brad Ebinger16417b42017-03-07 13:48:50 -0800825 *
826 * @deprecated Does not support MSIM devices. Please use
Brad Ebinger479f52c2017-08-28 13:19:22 -0700827 * {@link #isWfcEnabledByUser()} instead.
Etan Cohena00c9192014-12-23 15:02:29 -0800828 */
829 public static boolean isWfcEnabledByUser(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700830 ImsManager mgr = ImsManager.getInstance(context,
831 SubscriptionManager.getDefaultVoicePhoneId());
832 if (mgr != null) {
833 return mgr.isWfcEnabledByUser();
834 }
835 loge("isWfcEnabledByUser: ImsManager null, returning default value.");
836 return true;
Etan Cohena00c9192014-12-23 15:02:29 -0800837 }
838
839 /**
Malcolm Chen212ca652017-09-28 17:28:45 -0700840 * Returns the user configuration of WFC setting for slot. If not set, it
841 * queries CarrierConfig value as default.
Brad Ebinger16417b42017-03-07 13:48:50 -0800842 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700843 public boolean isWfcEnabledByUser() {
Malcolm Chen212ca652017-09-28 17:28:45 -0700844 int setting = SubscriptionManager.getIntegerSubscriptionProperty(
845 getSubId(), SubscriptionManager.WFC_IMS_ENABLED,
846 SUB_PROPERTY_NOT_INITIALIZED, mContext);
847
848 // SUB_PROPERTY_NOT_INITIALIZED indicates it's never set in sub db.
849 if (setting == SUB_PROPERTY_NOT_INITIALIZED) {
850 return getBooleanCarrierConfig(
851 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ENABLED_BOOL);
852 } else {
manabu, shimoda96aee542017-10-06 15:39:36 +0900853 return setting == ImsConfig.FeatureValueConstants.ON;
Malcolm Chen212ca652017-09-28 17:28:45 -0700854 }
Brad Ebinger16417b42017-03-07 13:48:50 -0800855 }
856
857 /**
858 * Change persistent WFC enabled setting.
859 * @deprecated Does not support MSIM devices. Please use
Brad Ebinger479f52c2017-08-28 13:19:22 -0700860 * {@link #setWfcSetting} instead.
Etan Cohena00c9192014-12-23 15:02:29 -0800861 */
862 public static void setWfcSetting(Context context, boolean enabled) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700863 ImsManager mgr = ImsManager.getInstance(context,
Etan Cohena00c9192014-12-23 15:02:29 -0800864 SubscriptionManager.getDefaultVoicePhoneId());
Brad Ebinger479f52c2017-08-28 13:19:22 -0700865 if (mgr != null) {
866 mgr.setWfcSetting(enabled);
Etan Cohena00c9192014-12-23 15:02:29 -0800867 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700868 loge("setWfcSetting: ImsManager null, can not set value.");
Etan Cohena00c9192014-12-23 15:02:29 -0800869 }
870
871 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800872 * Change persistent WFC enabled setting for slot.
873 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700874 public void setWfcSetting(boolean enabled) {
Malcolm Chen212ca652017-09-28 17:28:45 -0700875 SubscriptionManager.setSubscriptionProperty(getSubId(),
876 SubscriptionManager.WFC_IMS_ENABLED, booleanToPropertyString(enabled));
Brad Ebinger16417b42017-03-07 13:48:50 -0800877
Meng Wangeba31e12018-04-17 11:27:21 -0700878 TelephonyManager tm = (TelephonyManager)
879 mContext.getSystemService(Context.TELEPHONY_SERVICE);
880 setWfcNonPersistent(enabled, getWfcMode(tm.isNetworkRoaming(getSubId())));
Meng Wang51c09072017-03-27 10:47:45 -0700881 }
882
883 /**
884 * Non-persistently change WFC enabled setting and WFC mode for slot
885 *
886 * @param wfcMode The WFC preference if WFC is enabled
887 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700888 public void setWfcNonPersistent(boolean enabled, int wfcMode) {
Meng Wang51c09072017-03-27 10:47:45 -0700889 // Force IMS to register over LTE when turning off WFC
890 int imsWfcModeFeatureValue =
891 enabled ? wfcMode : ImsConfig.WfcModeFeatureValueConstants.CELLULAR_PREFERRED;
892
Brad Ebinger16417b42017-03-07 13:48:50 -0800893 try {
Brad Ebinger172977a2018-01-16 09:36:56 -0800894 changeMmTelCapability(MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE,
895 ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN, enabled);
Brad Ebinger16417b42017-03-07 13:48:50 -0800896
897 if (enabled) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700898 log("setWfcSetting() : turnOnIms");
Brad Ebinger16417b42017-03-07 13:48:50 -0800899 turnOnIms();
Brad Ebinger479f52c2017-08-28 13:19:22 -0700900 } else if (isTurnOffImsAllowedByPlatform()
901 && (!isVolteEnabledByPlatform()
902 || !isEnhanced4gLteModeSettingEnabledByUser())) {
903 log("setWfcSetting() : imsServiceAllowTurnOff -> turnOffIms");
Brad Ebinger16417b42017-03-07 13:48:50 -0800904 turnOffIms();
905 }
906
Brad Ebinger479f52c2017-08-28 13:19:22 -0700907 setWfcModeInternal(imsWfcModeFeatureValue);
Brad Ebinger172977a2018-01-16 09:36:56 -0800908 } catch (ImsException | RemoteException e) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700909 loge("setWfcSetting(): ", e);
Brad Ebinger16417b42017-03-07 13:48:50 -0800910 }
911 }
912
913 /**
914 * Returns the user configuration of WFC preference setting.
915 *
Malcolm Chen212ca652017-09-28 17:28:45 -0700916 * @deprecated Doesn't support MSIM devices. Use {@link #getWfcMode(boolean roaming)} instead.
Etan Cohena00c9192014-12-23 15:02:29 -0800917 */
918 public static int getWfcMode(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700919 ImsManager mgr = ImsManager.getInstance(context,
920 SubscriptionManager.getDefaultVoicePhoneId());
921 if (mgr != null) {
922 return mgr.getWfcMode();
923 }
924 loge("getWfcMode: ImsManager null, returning default value.");
925 return ImsConfig.WfcModeFeatureValueConstants.WIFI_ONLY;
Etan Cohena00c9192014-12-23 15:02:29 -0800926 }
927
928 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800929 * Returns the user configuration of WFC preference setting
Malcolm Chen212ca652017-09-28 17:28:45 -0700930 * @deprecated. Use {@link #getWfcMode(boolean roaming)} instead.
Brad Ebinger16417b42017-03-07 13:48:50 -0800931 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700932 public int getWfcMode() {
Malcolm Chen212ca652017-09-28 17:28:45 -0700933 return getWfcMode(false);
Brad Ebinger16417b42017-03-07 13:48:50 -0800934 }
935
936 /**
937 * Change persistent WFC preference setting.
938 *
Brad Ebinger479f52c2017-08-28 13:19:22 -0700939 * @deprecated Doesn't support MSIM devices. Use {@link #setWfcMode(int)} instead.
Etan Cohena00c9192014-12-23 15:02:29 -0800940 */
941 public static void setWfcMode(Context context, int wfcMode) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700942 ImsManager mgr = ImsManager.getInstance(context,
943 SubscriptionManager.getDefaultVoicePhoneId());
944 if (mgr != null) {
945 mgr.setWfcMode(wfcMode);
946 }
947 loge("setWfcMode: ImsManager null, can not set value.");
Pavel Zhamaitsiak9e6eca22015-03-16 15:30:53 -0700948 }
949
Meng Wang37477012016-09-20 09:59:56 -0700950 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800951 * Change persistent WFC preference setting for slot.
952 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700953 public void setWfcMode(int wfcMode) {
954 if (DBG) log("setWfcMode(i) - setting=" + wfcMode);
Malcolm Chen212ca652017-09-28 17:28:45 -0700955
956 SubscriptionManager.setSubscriptionProperty(getSubId(),
957 SubscriptionManager.WFC_IMS_MODE, Integer.toString(wfcMode));
Brad Ebinger16417b42017-03-07 13:48:50 -0800958
Brad Ebinger479f52c2017-08-28 13:19:22 -0700959 setWfcModeInternal(wfcMode);
Brad Ebinger16417b42017-03-07 13:48:50 -0800960 }
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 Ebinger74974e52018-05-01 16:16:47 -0700986 int setting;
Brad Ebinger16417b42017-03-07 13:48:50 -0800987 if (!roaming) {
Brad Ebinger74974e52018-05-01 16:16:47 -0700988 // The WFC mode is not editable, return the default setting in the CarrierConfig, not
989 // the user set value.
990 if (!getBooleanCarrierConfig(CarrierConfigManager.KEY_EDITABLE_WFC_MODE_BOOL)) {
Malcolm Chen212ca652017-09-28 17:28:45 -0700991 setting = getIntCarrierConfig(
992 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_MODE_INT);
Brad Ebinger74974e52018-05-01 16:16:47 -0700993
994 } else {
995 setting = getSettingFromSubscriptionManager(SubscriptionManager.WFC_IMS_MODE,
996 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_MODE_INT);
Malcolm Chen212ca652017-09-28 17:28:45 -0700997 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700998 if (DBG) log("getWfcMode - setting=" + setting);
Brad Ebinger16417b42017-03-07 13:48:50 -0800999 } else {
Brad Ebinger74974e52018-05-01 16:16:47 -07001000 // The WFC roaming mode is not editable, return the default setting in the
1001 // CarrierConfig, not the user set value.
1002 if (!getBooleanCarrierConfig(CarrierConfigManager.KEY_EDITABLE_WFC_MODE_BOOL)) {
Malcolm Chen212ca652017-09-28 17:28:45 -07001003 setting = getIntCarrierConfig(
1004 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_MODE_INT);
Malcolm Chen212ca652017-09-28 17:28:45 -07001005
Brad Ebinger74974e52018-05-01 16:16:47 -07001006 } else {
1007 setting = getSettingFromSubscriptionManager(
1008 SubscriptionManager.WFC_IMS_ROAMING_MODE,
1009 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_MODE_INT);
1010 }
Brad Ebinger479f52c2017-08-28 13:19:22 -07001011 if (DBG) log("getWfcMode (roaming) - setting=" + setting);
Brad Ebinger16417b42017-03-07 13:48:50 -08001012 }
1013 return setting;
1014 }
1015
1016 /**
Brad Ebinger74974e52018-05-01 16:16:47 -07001017 * Returns the SubscriptionManager setting for the subSetting string. If it is not set, default
1018 * to the default CarrierConfig value for defaultConfigKey.
1019 */
1020 private int getSettingFromSubscriptionManager(String subSetting, String defaultConfigKey) {
1021 int result;
1022 result = SubscriptionManager.getIntegerSubscriptionProperty(getSubId(), subSetting,
1023 SUB_PROPERTY_NOT_INITIALIZED, mContext);
1024
1025 // SUB_PROPERTY_NOT_INITIALIZED indicates it's never set in sub db.
1026 if (result == SUB_PROPERTY_NOT_INITIALIZED) {
1027 result = getIntCarrierConfig(defaultConfigKey);
1028 }
1029 return result;
1030 }
1031
1032 /**
Meng Wang37477012016-09-20 09:59:56 -07001033 * Change persistent WFC preference setting
1034 *
1035 * @param roaming {@code false} for home network setting, {@code true} for roaming setting
Brad Ebinger16417b42017-03-07 13:48:50 -08001036 *
Brad Ebinger479f52c2017-08-28 13:19:22 -07001037 * @deprecated Doesn't support MSIM devices. Please use {@link #setWfcMode(int, boolean)}
1038 * instead.
Meng Wang37477012016-09-20 09:59:56 -07001039 */
1040 public static void setWfcMode(Context context, int wfcMode, boolean roaming) {
Brad Ebinger479f52c2017-08-28 13:19:22 -07001041 ImsManager mgr = ImsManager.getInstance(context,
1042 SubscriptionManager.getDefaultVoicePhoneId());
1043 if (mgr != null) {
1044 mgr.setWfcMode(wfcMode, roaming);
Meng Wang37477012016-09-20 09:59:56 -07001045 }
Brad Ebinger479f52c2017-08-28 13:19:22 -07001046 loge("setWfcMode: ImsManager null, can not set value.");
Meng Wang37477012016-09-20 09:59:56 -07001047 }
1048
Brad Ebinger16417b42017-03-07 13:48:50 -08001049 /**
1050 * Change persistent WFC preference setting
1051 *
1052 * @param roaming {@code false} for home network setting, {@code true} for roaming setting
1053 */
Brad Ebinger479f52c2017-08-28 13:19:22 -07001054 public void setWfcMode(int wfcMode, boolean roaming) {
Brad Ebinger16417b42017-03-07 13:48:50 -08001055 if (!roaming) {
Brad Ebinger479f52c2017-08-28 13:19:22 -07001056 if (DBG) log("setWfcMode(i,b) - setting=" + wfcMode);
Malcolm Chen212ca652017-09-28 17:28:45 -07001057 SubscriptionManager.setSubscriptionProperty(getSubId(),
1058 SubscriptionManager.WFC_IMS_MODE, Integer.toString(wfcMode));
Brad Ebinger16417b42017-03-07 13:48:50 -08001059 } else {
Brad Ebinger479f52c2017-08-28 13:19:22 -07001060 if (DBG) log("setWfcMode(i,b) (roaming) - setting=" + wfcMode);
Malcolm Chen212ca652017-09-28 17:28:45 -07001061 SubscriptionManager.setSubscriptionProperty(getSubId(),
1062 SubscriptionManager.WFC_IMS_ROAMING_MODE, Integer.toString(wfcMode));
Brad Ebinger16417b42017-03-07 13:48:50 -08001063 }
1064
Brad Ebinger479f52c2017-08-28 13:19:22 -07001065 TelephonyManager tm = (TelephonyManager)
1066 mContext.getSystemService(Context.TELEPHONY_SERVICE);
1067 if (roaming == tm.isNetworkRoaming(getSubId())) {
1068 setWfcModeInternal(wfcMode);
1069 }
1070 }
1071
1072 private int getSubId() {
Brad Ebinger16417b42017-03-07 13:48:50 -08001073 int[] subIds = SubscriptionManager.getSubId(mPhoneId);
1074 int subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1075 if (subIds != null && subIds.length >= 1) {
1076 subId = subIds[0];
1077 }
Brad Ebinger479f52c2017-08-28 13:19:22 -07001078 return subId;
Brad Ebinger16417b42017-03-07 13:48:50 -08001079 }
1080
Brad Ebinger479f52c2017-08-28 13:19:22 -07001081 private void setWfcModeInternal(int wfcMode) {
Brad Ebinger16417b42017-03-07 13:48:50 -08001082 final int value = wfcMode;
1083 Thread thread = new Thread(() -> {
Malcolm Chen212ca652017-09-28 17:28:45 -07001084 try {
Brad Ebinger172977a2018-01-16 09:36:56 -08001085 getConfigInterface().setConfig(
Malcolm Chen212ca652017-09-28 17:28:45 -07001086 ImsConfig.ConfigConstants.VOICE_OVER_WIFI_MODE, value);
1087 } catch (ImsException e) {
1088 // do nothing
1089 }
Brad Ebinger16417b42017-03-07 13:48:50 -08001090 });
1091 thread.start();
1092 }
1093
Etan Cohena00c9192014-12-23 15:02:29 -08001094 /**
1095 * Returns the user configuration of WFC roaming setting
Brad Ebinger16417b42017-03-07 13:48:50 -08001096 *
1097 * @deprecated Does not support MSIM devices. Please use
Brad Ebinger479f52c2017-08-28 13:19:22 -07001098 * {@link #isWfcRoamingEnabledByUser()} instead.
Etan Cohena00c9192014-12-23 15:02:29 -08001099 */
1100 public static boolean isWfcRoamingEnabledByUser(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -07001101 ImsManager mgr = ImsManager.getInstance(context,
1102 SubscriptionManager.getDefaultVoicePhoneId());
1103 if (mgr != null) {
1104 return mgr.isWfcRoamingEnabledByUser();
1105 }
1106 loge("isWfcRoamingEnabledByUser: ImsManager null, returning default value.");
1107 return false;
Etan Cohena00c9192014-12-23 15:02:29 -08001108 }
1109
1110 /**
Malcolm Chen212ca652017-09-28 17:28:45 -07001111 * Returns the user configuration of WFC roaming setting for slot. If not set, it
1112 * queries CarrierConfig value as default.
Brad Ebinger16417b42017-03-07 13:48:50 -08001113 */
Brad Ebinger479f52c2017-08-28 13:19:22 -07001114 public boolean isWfcRoamingEnabledByUser() {
Malcolm Chen212ca652017-09-28 17:28:45 -07001115 int setting = SubscriptionManager.getIntegerSubscriptionProperty(
1116 getSubId(), SubscriptionManager.WFC_IMS_ROAMING_ENABLED,
1117 SUB_PROPERTY_NOT_INITIALIZED, mContext);
1118 if (setting == SUB_PROPERTY_NOT_INITIALIZED) {
1119 return getBooleanCarrierConfig(
1120 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_ENABLED_BOOL);
1121 } else {
manabu, shimoda96aee542017-10-06 15:39:36 +09001122 return setting == ImsConfig.FeatureValueConstants.ON;
Malcolm Chen212ca652017-09-28 17:28:45 -07001123 }
Brad Ebinger16417b42017-03-07 13:48:50 -08001124 }
1125
1126 /**
Etan Cohena00c9192014-12-23 15:02:29 -08001127 * Change persistent WFC roaming enabled setting
1128 */
1129 public static void setWfcRoamingSetting(Context context, boolean enabled) {
Brad Ebinger479f52c2017-08-28 13:19:22 -07001130 ImsManager mgr = ImsManager.getInstance(context,
Etan Cohena00c9192014-12-23 15:02:29 -08001131 SubscriptionManager.getDefaultVoicePhoneId());
Brad Ebinger479f52c2017-08-28 13:19:22 -07001132 if (mgr != null) {
1133 mgr.setWfcRoamingSetting(enabled);
Etan Cohena00c9192014-12-23 15:02:29 -08001134 }
Brad Ebinger479f52c2017-08-28 13:19:22 -07001135 loge("setWfcRoamingSetting: ImsManager null, value not set.");
Etan Cohena00c9192014-12-23 15:02:29 -08001136 }
1137
1138 /**
Brad Ebinger16417b42017-03-07 13:48:50 -08001139 * Change persistent WFC roaming enabled setting
1140 */
Brad Ebinger479f52c2017-08-28 13:19:22 -07001141 public void setWfcRoamingSetting(boolean enabled) {
Malcolm Chen212ca652017-09-28 17:28:45 -07001142 SubscriptionManager.setSubscriptionProperty(getSubId(),
1143 SubscriptionManager.WFC_IMS_ROAMING_ENABLED, booleanToPropertyString(enabled)
1144 );
Brad Ebinger16417b42017-03-07 13:48:50 -08001145
1146 setWfcRoamingSettingInternal(enabled);
1147 }
1148
1149 private void setWfcRoamingSettingInternal(boolean enabled) {
1150 final int value = enabled
1151 ? ImsConfig.FeatureValueConstants.ON
1152 : ImsConfig.FeatureValueConstants.OFF;
1153 Thread thread = new Thread(() -> {
Malcolm Chen212ca652017-09-28 17:28:45 -07001154 try {
Brad Ebinger172977a2018-01-16 09:36:56 -08001155 getConfigInterface().setConfig(
Malcolm Chen212ca652017-09-28 17:28:45 -07001156 ImsConfig.ConfigConstants.VOICE_OVER_WIFI_ROAMING, value);
1157 } catch (ImsException e) {
1158 // do nothing
1159 }
Brad Ebinger16417b42017-03-07 13:48:50 -08001160 });
1161 thread.start();
1162 }
1163
1164 /**
Etan Cohena00c9192014-12-23 15:02:29 -08001165 * Returns a platform configuration for WFC which may override the user
1166 * setting. Note: WFC presumes that VoLTE is enabled (these are
1167 * configuration settings which must be done correctly).
Brad Ebinger16417b42017-03-07 13:48:50 -08001168 *
Brad Ebinger479f52c2017-08-28 13:19:22 -07001169 * @deprecated Doesn't work for MSIM devices. Use {@link #isWfcEnabledByPlatform()}
Brad Ebinger16417b42017-03-07 13:48:50 -08001170 * instead.
Etan Cohena00c9192014-12-23 15:02:29 -08001171 */
1172 public static boolean isWfcEnabledByPlatform(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -07001173 ImsManager mgr = ImsManager.getInstance(context,
1174 SubscriptionManager.getDefaultVoicePhoneId());
1175 if (mgr != null) {
1176 return mgr.isWfcEnabledByPlatform();
Etan Cohena00c9192014-12-23 15:02:29 -08001177 }
Brad Ebinger479f52c2017-08-28 13:19:22 -07001178 loge("isWfcEnabledByPlatform: ImsManager null, returning default value.");
1179 return false;
Pavel Zhamaitsiak57911d12015-10-20 14:26:34 -07001180 }
1181
1182 /**
Brad Ebinger16417b42017-03-07 13:48:50 -08001183 * Returns a platform configuration for WFC which may override the user
1184 * setting per slot. Note: WFC presumes that VoLTE is enabled (these are
1185 * configuration settings which must be done correctly).
1186 */
Brad Ebinger479f52c2017-08-28 13:19:22 -07001187 public boolean isWfcEnabledByPlatform() {
Malcolm Chen18837ff2017-10-25 17:05:41 -07001188 // We first read the per slot value. If doesn't exist, we read the general value. If still
1189 // doesn't exist, we use the hardcoded default value.
1190 if (SystemProperties.getInt(PROPERTY_DBG_WFC_AVAIL_OVERRIDE +
1191 Integer.toString(mPhoneId), SYSTEM_PROPERTY_NOT_SET) == 1 ||
1192 SystemProperties.getInt(
1193 PROPERTY_DBG_WFC_AVAIL_OVERRIDE, SYSTEM_PROPERTY_NOT_SET) == 1) {
Brad Ebinger16417b42017-03-07 13:48:50 -08001194 return true;
1195 }
1196
1197 return mContext.getResources().getBoolean(
1198 com.android.internal.R.bool.config_device_wfc_ims_available) &&
Brad Ebinger479f52c2017-08-28 13:19:22 -07001199 getBooleanCarrierConfig(
Brad Ebinger16417b42017-03-07 13:48:50 -08001200 CarrierConfigManager.KEY_CARRIER_WFC_IMS_AVAILABLE_BOOL) &&
Brad Ebinger479f52c2017-08-28 13:19:22 -07001201 isGbaValid();
Etan Cohena00c9192014-12-23 15:02:29 -08001202 }
1203
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001204 /**
Brad Ebinger16417b42017-03-07 13:48:50 -08001205 * If carrier requires that IMS is only available if GBA capable SIM is used,
1206 * then this function checks GBA bit in EF IST.
1207 *
1208 * Format of EF IST is defined in 3GPP TS 31.103 (Section 4.2.7).
1209 */
Brad Ebinger479f52c2017-08-28 13:19:22 -07001210 private boolean isGbaValid() {
1211 if (getBooleanCarrierConfig(
Brad Ebinger16417b42017-03-07 13:48:50 -08001212 CarrierConfigManager.KEY_CARRIER_IMS_GBA_REQUIRED_BOOL)) {
Brad Ebinger479f52c2017-08-28 13:19:22 -07001213 final TelephonyManager telephonyManager = new TelephonyManager(mContext, getSubId());
Brad Ebinger16417b42017-03-07 13:48:50 -08001214 String efIst = telephonyManager.getIsimIst();
1215 if (efIst == null) {
Brad Ebinger479f52c2017-08-28 13:19:22 -07001216 loge("isGbaValid - ISF is NULL");
Brad Ebinger16417b42017-03-07 13:48:50 -08001217 return true;
1218 }
1219 boolean result = efIst != null && efIst.length() > 1 &&
1220 (0x02 & (byte)efIst.charAt(1)) != 0;
Brad Ebinger479f52c2017-08-28 13:19:22 -07001221 if (DBG) log("isGbaValid - GBA capable=" + result + ", ISF=" + efIst);
Brad Ebinger16417b42017-03-07 13:48:50 -08001222 return result;
1223 }
1224 return true;
1225 }
1226
1227 /**
Malcolm Chen18837ff2017-10-25 17:05:41 -07001228 * Will return with config value or throw an ImsException if we receive an error from
1229 * ImsConfig for that value.
1230 */
1231 private boolean getProvisionedBool(ImsConfig config, int item) throws ImsException {
1232 int value = config.getProvisionedValue(item);
1233 if (value == ImsConfig.OperationStatusConstants.UNKNOWN) {
1234 throw new ImsException("getProvisionedBool failed with error for item: " + item,
1235 ImsReasonInfo.CODE_LOCAL_INTERNAL_ERROR);
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -07001236 }
Malcolm Chen18837ff2017-10-25 17:05:41 -07001237 return config.getProvisionedValue(item) == ImsConfig.FeatureValueConstants.ON;
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -07001238 }
1239
1240 /**
Malcolm Chen18837ff2017-10-25 17:05:41 -07001241 * Will return with config value or return false if we receive an error from
1242 * ImsConfig for that value.
Brad Ebingerbe6cb672017-08-25 14:55:00 -07001243 */
Malcolm Chen18837ff2017-10-25 17:05:41 -07001244 private boolean getProvisionedBoolNoException(int item) {
1245 try {
1246 ImsConfig config = getConfigInterface();
1247 return getProvisionedBool(config, item);
1248 } catch (ImsException ex) {
1249 return false;
Brad Ebingerbe6cb672017-08-25 14:55:00 -07001250 }
1251 }
1252
1253 /**
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001254 * Sync carrier config and user settings with ImsConfig.
1255 *
1256 * @param context for the manager object
1257 * @param phoneId phone id
1258 * @param force update
Brad Ebinger16417b42017-03-07 13:48:50 -08001259 *
Brad Ebinger479f52c2017-08-28 13:19:22 -07001260 * @deprecated Doesn't support MSIM devices. Use {@link #updateImsServiceConfig(boolean)}
1261 * instead.
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001262 */
1263 public static void updateImsServiceConfig(Context context, int phoneId, boolean force) {
Brad Ebinger479f52c2017-08-28 13:19:22 -07001264 ImsManager mgr = ImsManager.getInstance(context, phoneId);
1265 if (mgr != null) {
1266 mgr.updateImsServiceConfig(force);
Pavel Zhamaitsiakfc202992016-03-29 18:07:38 -07001267 }
Brad Ebinger479f52c2017-08-28 13:19:22 -07001268 loge("updateImsServiceConfig: ImsManager null, returning without update.");
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001269 }
1270
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -07001271 /**
Brad Ebinger16417b42017-03-07 13:48:50 -08001272 * Sync carrier config and user settings with ImsConfig.
1273 *
Brad Ebinger16417b42017-03-07 13:48:50 -08001274 * @param force update
1275 */
Brad Ebinger479f52c2017-08-28 13:19:22 -07001276 public void updateImsServiceConfig(boolean force) {
Brad Ebinger16417b42017-03-07 13:48:50 -08001277 if (!force) {
Brad Ebinger479f52c2017-08-28 13:19:22 -07001278 TelephonyManager tm = new TelephonyManager(mContext, getSubId());
1279 if (tm.getSimState() != TelephonyManager.SIM_STATE_READY) {
1280 log("updateImsServiceConfig: SIM not ready");
Brad Ebinger16417b42017-03-07 13:48:50 -08001281 // Don't disable IMS if SIM is not ready
1282 return;
1283 }
1284 }
1285
1286 if (!mConfigUpdated || force) {
1287 try {
Brad Ebinger16417b42017-03-07 13:48:50 -08001288 // TODO: Extend ImsConfig API and set all feature values in single function call.
1289
1290 // Note: currently the order of updates is set to produce different order of
Brad Ebinger172977a2018-01-16 09:36:56 -08001291 // changeEnabledCapabilities() function calls from setAdvanced4GMode(). This is done
1292 // to differentiate this code path from vendor code perspective.
Brad Ebinger16417b42017-03-07 13:48:50 -08001293 boolean isImsUsed = updateVolteFeatureValue();
1294 isImsUsed |= updateWfcFeatureAndProvisionedValues();
1295 isImsUsed |= updateVideoCallFeatureValue();
1296
Brad Ebinger479f52c2017-08-28 13:19:22 -07001297 if (isImsUsed || !isTurnOffImsAllowedByPlatform()) {
Brad Ebinger16417b42017-03-07 13:48:50 -08001298 // Turn on IMS if it is used.
1299 // Also, if turning off is not allowed for current carrier,
1300 // we need to turn IMS on because it might be turned off before
1301 // phone switched to current carrier.
Brad Ebinger479f52c2017-08-28 13:19:22 -07001302 log("updateImsServiceConfig: turnOnIms");
Brad Ebinger16417b42017-03-07 13:48:50 -08001303 turnOnIms();
1304 } else {
1305 // Turn off IMS if it is not used AND turning off is allowed for carrier.
Brad Ebinger479f52c2017-08-28 13:19:22 -07001306 log("updateImsServiceConfig: turnOffIms");
Brad Ebinger16417b42017-03-07 13:48:50 -08001307 turnOffIms();
1308 }
1309
1310 mConfigUpdated = true;
Brad Ebinger172977a2018-01-16 09:36:56 -08001311 } catch (ImsException | RemoteException e) {
Brad Ebinger479f52c2017-08-28 13:19:22 -07001312 loge("updateImsServiceConfig: ", e);
Brad Ebinger16417b42017-03-07 13:48:50 -08001313 mConfigUpdated = false;
1314 }
1315 }
1316 }
1317
1318 /**
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -07001319 * Update VoLTE config
1320 * @return whether feature is On
1321 * @throws ImsException
1322 */
Brad Ebinger172977a2018-01-16 09:36:56 -08001323 private boolean updateVolteFeatureValue() throws RemoteException {
Brad Ebinger479f52c2017-08-28 13:19:22 -07001324 boolean available = isVolteEnabledByPlatform();
1325 boolean enabled = isEnhanced4gLteModeSettingEnabledByUser();
1326 boolean isNonTty = isNonTtyOrTtyOnVolteEnabled();
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -08001327 boolean isFeatureOn = available && enabled && isNonTty;
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001328
1329 log("updateVolteFeatureValue: available = " + available
1330 + ", enabled = " + enabled
1331 + ", nonTTY = " + isNonTty);
1332
Brad Ebinger172977a2018-01-16 09:36:56 -08001333 changeMmTelCapability(MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE,
1334 ImsRegistrationImplBase.REGISTRATION_TECH_LTE, isFeatureOn);
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -07001335
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -08001336 return isFeatureOn;
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001337 }
1338
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -07001339 /**
Jack Yu643ffe42016-07-08 14:25:46 -07001340 * Update video call over LTE config
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -07001341 * @return whether feature is On
1342 * @throws ImsException
1343 */
Brad Ebinger172977a2018-01-16 09:36:56 -08001344 private boolean updateVideoCallFeatureValue() throws RemoteException {
Brad Ebinger479f52c2017-08-28 13:19:22 -07001345 boolean available = isVtEnabledByPlatform();
1346 boolean enabled = isVtEnabledByUser();
1347 boolean isNonTty = isNonTtyOrTtyOnVolteEnabled();
Amit Mahajan24f7b162016-07-21 16:33:53 -07001348 boolean isDataEnabled = isDataEnabled();
Brad Ebinger479f52c2017-08-28 13:19:22 -07001349 boolean ignoreDataEnabledChanged = getBooleanCarrierConfig(
Jack Yu57781852016-11-16 17:20:38 -08001350 CarrierConfigManager.KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS);
Jack Yu643ffe42016-07-08 14:25:46 -07001351
Jack Yu57781852016-11-16 17:20:38 -08001352 boolean isFeatureOn = available && enabled && isNonTty
1353 && (ignoreDataEnabledChanged || isDataEnabled);
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001354
1355 log("updateVideoCallFeatureValue: available = " + available
1356 + ", enabled = " + enabled
Jack Yu643ffe42016-07-08 14:25:46 -07001357 + ", nonTTY = " + isNonTty
Amit Mahajan24f7b162016-07-21 16:33:53 -07001358 + ", data enabled = " + isDataEnabled);
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001359
Brad Ebinger172977a2018-01-16 09:36:56 -08001360 changeMmTelCapability(MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VIDEO,
1361 ImsRegistrationImplBase.REGISTRATION_TECH_LTE, isFeatureOn);
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -07001362
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -08001363 return isFeatureOn;
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001364 }
1365
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -07001366 /**
1367 * Update WFC config
1368 * @return whether feature is On
1369 * @throws ImsException
1370 */
Brad Ebinger172977a2018-01-16 09:36:56 -08001371 private boolean updateWfcFeatureAndProvisionedValues() throws RemoteException {
Brad Ebinger479f52c2017-08-28 13:19:22 -07001372 TelephonyManager tm = new TelephonyManager(mContext, getSubId());
1373 boolean isNetworkRoaming = tm.isNetworkRoaming();
1374 boolean available = isWfcEnabledByPlatform();
1375 boolean enabled = isWfcEnabledByUser();
Brad Ebinger479f52c2017-08-28 13:19:22 -07001376 int mode = getWfcMode(isNetworkRoaming);
1377 boolean roaming = isWfcRoamingEnabledByUser();
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -08001378 boolean isFeatureOn = available && enabled;
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001379
1380 log("updateWfcFeatureAndProvisionedValues: available = " + available
1381 + ", enabled = " + enabled
1382 + ", mode = " + mode
1383 + ", roaming = " + roaming);
1384
Brad Ebinger172977a2018-01-16 09:36:56 -08001385 changeMmTelCapability(MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE,
1386 ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN, isFeatureOn);
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001387
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -08001388 if (!isFeatureOn) {
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001389 mode = ImsConfig.WfcModeFeatureValueConstants.CELLULAR_PREFERRED;
1390 roaming = false;
1391 }
Brad Ebinger74974e52018-05-01 16:16:47 -07001392 setWfcModeInternal(mode);
Brad Ebinger16417b42017-03-07 13:48:50 -08001393 setWfcRoamingSettingInternal(roaming);
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -07001394
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -08001395 return isFeatureOn;
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001396 }
1397
Brad Ebinger16780ff2017-01-26 11:18:21 -08001398 /**
Brad Ebinger479f52c2017-08-28 13:19:22 -07001399 * Do NOT use this directly, instead use {@link #getInstance(Context, int)}.
Brad Ebinger16780ff2017-01-26 11:18:21 -08001400 */
1401 @VisibleForTesting
1402 public ImsManager(Context context, int phoneId) {
Wink Savilleef36ef62014-06-11 08:39:38 -07001403 mContext = context;
Etan Cohenabbd7882014-09-26 22:35:35 -07001404 mPhoneId = phoneId;
Brad Ebinger16780ff2017-01-26 11:18:21 -08001405 mConfigDynamicBind = mContext.getResources().getBoolean(
1406 com.android.internal.R.bool.config_dynamic_bind_ims);
Brad Ebinger16417b42017-03-07 13:48:50 -08001407 mConfigManager = (CarrierConfigManager) context.getSystemService(
1408 Context.CARRIER_CONFIG_SERVICE);
Brad Ebinger16780ff2017-01-26 11:18:21 -08001409 createImsService();
1410 }
1411
1412 /**
Brad Ebinger16780ff2017-01-26 11:18:21 -08001413 * @return Whether or not ImsManager is configured to Dynamically bind or not to support legacy
1414 * devices.
1415 */
1416 public boolean isDynamicBinding() {
1417 return mConfigDynamicBind;
Wink Savilleef36ef62014-06-11 08:39:38 -07001418 }
1419
Etan Cohenf4311122015-02-26 17:47:13 -08001420 /*
Brad Ebinger0aed76d2018-03-05 16:39:02 -08001421 * Returns a flag indicating whether the IMS service is available. If it is not available or
1422 * busy, it will try to connect before reporting failure.
Etan Cohenf4311122015-02-26 17:47:13 -08001423 */
1424 public boolean isServiceAvailable() {
Brad Ebinger0aed76d2018-03-05 16:39:02 -08001425 // If we are busy resolving dynamic IMS bindings, we are not available yet.
1426 TelephonyManager tm = (TelephonyManager)
1427 mContext.getSystemService(Context.TELEPHONY_SERVICE);
1428 if (tm.isResolvingImsBinding()) {
1429 Log.d(TAG, "isServiceAvailable: resolving IMS binding, returning false");
1430 return false;
1431 }
1432
Brad Ebingerff097922017-06-19 15:43:08 -07001433 connectIfServiceIsAvailable();
Brad Ebinger16780ff2017-01-26 11:18:21 -08001434 // mImsServiceProxy will always create an ImsServiceProxy.
Brad Ebinger172977a2018-01-16 09:36:56 -08001435 return mMmTelFeatureConnection.isBinderAlive();
Etan Cohenf4311122015-02-26 17:47:13 -08001436 }
1437
Suresh Koleticc3139c2017-11-03 18:23:57 +05301438 /*
1439 * Returns a flag indicating whether the IMS service is ready to send requests to lower layers.
1440 */
1441 public boolean isServiceReady() {
1442 connectIfServiceIsAvailable();
Brad Ebinger172977a2018-01-16 09:36:56 -08001443 return mMmTelFeatureConnection.isBinderReady();
Suresh Koleticc3139c2017-11-03 18:23:57 +05301444 }
1445
Brad Ebingerff097922017-06-19 15:43:08 -07001446 /**
1447 * If the service is available, try to reconnect.
1448 */
1449 public void connectIfServiceIsAvailable() {
Brad Ebinger172977a2018-01-16 09:36:56 -08001450 if (mMmTelFeatureConnection == null || !mMmTelFeatureConnection.isBinderAlive()) {
Brad Ebingerff097922017-06-19 15:43:08 -07001451 createImsService();
1452 }
1453 }
1454
Brad Ebinger172977a2018-01-16 09:36:56 -08001455 public void setConfigListener(ImsConfigListener listener) {
Pavel Zhamaitsiakf4b90322016-01-26 14:34:09 -08001456 mImsConfigListener = listener;
1457 }
1458
Brad Ebingerb10b61e2017-04-18 11:45:26 -07001459
1460 /**
1461 * Adds a callback for status changed events if the binder is already available. If it is not,
1462 * this method will throw an ImsException.
1463 */
Brad Ebinger6ddf28e2018-02-21 16:07:23 -08001464 @VisibleForTesting
Brad Ebinger172977a2018-01-16 09:36:56 -08001465 public void addNotifyStatusChangedCallbackIfAvailable(MmTelFeatureConnection.IFeatureUpdate c)
Brad Ebingerb10b61e2017-04-18 11:45:26 -07001466 throws ImsException {
Brad Ebinger172977a2018-01-16 09:36:56 -08001467 if (!mMmTelFeatureConnection.isBinderAlive()) {
Brad Ebingerb10b61e2017-04-18 11:45:26 -07001468 throw new ImsException("Binder is not active!",
1469 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1470 }
Brad Ebinger16780ff2017-01-26 11:18:21 -08001471 if (c != null) {
1472 mStatusCallbacks.add(c);
1473 }
1474 }
1475
Brad Ebinger6ddf28e2018-02-21 16:07:23 -08001476 void removeNotifyStatusChangedCallback(MmTelFeatureConnection.IFeatureUpdate c) {
Brad Ebinger44fd8af2017-12-14 14:24:02 -08001477 if (c != null) {
1478 mStatusCallbacks.remove(c);
1479 } else {
1480 Log.w(TAG, "removeNotifyStatusChangedCallback: callback is null!");
1481 }
1482 }
1483
Wink Savilleef36ef62014-06-11 08:39:38 -07001484 /**
1485 * Opens the IMS service for making calls and/or receiving generic IMS calls.
Brad Ebinger172977a2018-01-16 09:36:56 -08001486 * The caller may make subsequent calls through {@link #makeCall}.
Wink Savilleef36ef62014-06-11 08:39:38 -07001487 * The IMS service will register the device to the operator's network with the credentials
1488 * (from ISIM) periodically in order to receive calls from the operator's network.
Brad Ebinger172977a2018-01-16 09:36:56 -08001489 * When the IMS service receives a new call, it will call
1490 * {@link MmTelFeature.Listener#onIncomingCall}
1491 * The listener contains a call ID extra {@link #getCallId} and it can be used to take a call.
1492 * @param listener A {@link MmTelFeature.Listener}, which is the interface the
1493 * {@link MmTelFeature} uses to notify the framework of updates
1494 * @throws NullPointerException if {@code listener} is null
Wink Savilleef36ef62014-06-11 08:39:38 -07001495 * @throws ImsException if calling the IMS service results in an error
1496 * @see #getCallId
Wink Savilleef36ef62014-06-11 08:39:38 -07001497 */
Brad Ebinger172977a2018-01-16 09:36:56 -08001498 public void open(MmTelFeature.Listener listener) throws ImsException {
Wink Savilleef36ef62014-06-11 08:39:38 -07001499 checkAndThrowExceptionIfServiceUnavailable();
1500
Wink Savilleef36ef62014-06-11 08:39:38 -07001501 if (listener == null) {
1502 throw new NullPointerException("listener can't be null");
1503 }
1504
Wink Savilleef36ef62014-06-11 08:39:38 -07001505 try {
Brad Ebinger172977a2018-01-16 09:36:56 -08001506 mMmTelFeatureConnection.openConnection(listener);
Wink Savilleef36ef62014-06-11 08:39:38 -07001507 } catch (RemoteException e) {
Brad Ebinger172977a2018-01-16 09:36:56 -08001508 throw new ImsException("open()", e, ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
Wink Savilleef36ef62014-06-11 08:39:38 -07001509 }
Wink Savilleef36ef62014-06-11 08:39:38 -07001510 }
1511
1512 /**
Pavel Zhamaitsiakce410172016-04-15 10:55:56 -07001513 * Adds registration listener to the IMS service.
1514 *
1515 * @param serviceClass a service class specified in {@link ImsServiceClass}
1516 * For VoLTE service, it MUST be a {@link ImsServiceClass#MMTEL}.
1517 * @param listener To listen to IMS registration events; It cannot be null
1518 * @throws NullPointerException if {@code listener} is null
1519 * @throws ImsException if calling the IMS service results in an error
Brad Ebinger9a0280c2017-06-01 15:58:48 -07001520 *
1521 * @deprecated Use {@link #addRegistrationListener(ImsConnectionStateListener)} instead.
Pavel Zhamaitsiakce410172016-04-15 10:55:56 -07001522 */
1523 public void addRegistrationListener(int serviceClass, ImsConnectionStateListener listener)
1524 throws ImsException {
Brad Ebinger9a0280c2017-06-01 15:58:48 -07001525 addRegistrationListener(listener);
1526 }
1527
1528 /**
1529 * Adds registration listener to the IMS service.
1530 *
1531 * @param listener To listen to IMS registration events; It cannot be null
1532 * @throws NullPointerException if {@code listener} is null
1533 * @throws ImsException if calling the IMS service results in an error
Brad Ebinger172977a2018-01-16 09:36:56 -08001534 * @deprecated use {@link #addRegistrationCallback(ImsRegistrationImplBase.Callback)} and
1535 * {@link #addCapabilitiesCallback(ImsFeature.CapabilityCallback)} instead.
Brad Ebinger9a0280c2017-06-01 15:58:48 -07001536 */
Brad Ebinger44fd8af2017-12-14 14:24:02 -08001537 public void addRegistrationListener(ImsConnectionStateListener listener) throws ImsException {
Pavel Zhamaitsiakce410172016-04-15 10:55:56 -07001538 if (listener == null) {
1539 throw new NullPointerException("listener can't be null");
1540 }
Brad Ebinger172977a2018-01-16 09:36:56 -08001541 addRegistrationCallback(listener);
1542 // connect the ImsConnectionStateListener to the new CapabilityCallback.
1543 addCapabilitiesCallback(new ImsFeature.CapabilityCallback() {
1544 @Override
1545 public void onCapabilitiesStatusChanged(ImsFeature.Capabilities config) {
1546 listener.onFeatureCapabilityChangedAdapter(getRegistrationTech(), config);
Brad Ebinger9a0280c2017-06-01 15:58:48 -07001547 }
Brad Ebinger172977a2018-01-16 09:36:56 -08001548 });
1549 log("Registration Callback registered.");
1550 }
1551
1552 /**
1553 * Adds a callback that gets called when IMS registration has changed.
1554 * @param callback A {@link ImsRegistrationImplBase.Callback} that will notify the caller when
1555 * IMS registration status has changed.
1556 * @throws ImsException when the ImsService connection is not available.
1557 */
1558 public void addRegistrationCallback(ImsRegistrationImplBase.Callback callback)
1559 throws ImsException {
1560 if (callback == null) {
1561 throw new NullPointerException("registration callback can't be null");
Brad Ebinger9a0280c2017-06-01 15:58:48 -07001562 }
Brad Ebinger172977a2018-01-16 09:36:56 -08001563
Brad Ebinger172977a2018-01-16 09:36:56 -08001564 try {
1565 mMmTelFeatureConnection.addRegistrationCallback(callback);
1566 log("Registration Callback registered.");
1567 // Only record if there isn't a RemoteException.
1568 } catch (RemoteException e) {
1569 throw new ImsException("addRegistrationCallback(IRIB)", e,
1570 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1571 }
1572 }
1573
1574 /**
Brad Ebingerd1b1a3c2018-03-08 11:37:35 -08001575 * Removes a previously added registration callback that was added via
1576 * {@link #addRegistrationCallback(ImsRegistrationImplBase.Callback)} .
1577 * @param callback A {@link ImsRegistrationImplBase.Callback} that was previously added.
1578 * @throws ImsException when the ImsService connection is not available.
1579 */
1580 public void removeRegistrationListener(ImsRegistrationImplBase.Callback callback)
1581 throws ImsException {
1582 if (callback == null) {
1583 throw new NullPointerException("registration callback can't be null");
1584 }
1585
1586 try {
1587 mMmTelFeatureConnection.removeRegistrationCallback(callback);
1588 log("Registration callback removed.");
1589 } catch (RemoteException e) {
1590 throw new ImsException("removeRegistrationCallback(IRIB)", e,
1591 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1592 }
1593 }
1594
1595 /**
Brad Ebinger172977a2018-01-16 09:36:56 -08001596 * Adds a callback that gets called when MMTel capability status has changed, for example when
1597 * Voice over IMS or VT over IMS is not available currently.
1598 * @param callback A {@link ImsFeature.CapabilityCallback} that will notify the caller when
1599 * MMTel capability status has changed.
1600 * @throws ImsException when the ImsService connection is not available.
1601 */
1602 public void addCapabilitiesCallback(ImsFeature.CapabilityCallback callback)
1603 throws ImsException {
1604 if (callback == null) {
1605 throw new NullPointerException("capabilities callback can't be null");
1606 }
1607
1608 checkAndThrowExceptionIfServiceUnavailable();
1609 try {
1610 mMmTelFeatureConnection.addCapabilityCallback(callback);
1611 log("Capability Callback registered.");
1612 // Only record if there isn't a RemoteException.
1613 } catch (RemoteException e) {
1614 throw new ImsException("addCapabilitiesCallback(IF)", e,
1615 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
Pavel Zhamaitsiakce410172016-04-15 10:55:56 -07001616 }
1617 }
1618
1619 /**
Brad Ebinger16780ff2017-01-26 11:18:21 -08001620 * Removes the registration listener from the IMS service.
1621 *
Brad Ebinger16780ff2017-01-26 11:18:21 -08001622 * @param listener Previously registered listener that will be removed. Can not be null.
1623 * @throws NullPointerException if {@code listener} is null
1624 * @throws ImsException if calling the IMS service results in an error
1625 * instead.
1626 */
Brad Ebingerb5f30c72017-02-17 14:54:31 -08001627 public void removeRegistrationListener(ImsConnectionStateListener listener)
Brad Ebinger16780ff2017-01-26 11:18:21 -08001628 throws ImsException {
Brad Ebinger16780ff2017-01-26 11:18:21 -08001629 if (listener == null) {
1630 throw new NullPointerException("listener can't be null");
1631 }
1632
Brad Ebinger172977a2018-01-16 09:36:56 -08001633 checkAndThrowExceptionIfServiceUnavailable();
1634 try {
1635 mMmTelFeatureConnection.removeRegistrationCallback(listener);
1636 log("Registration Callback/Listener registered.");
1637 // Only record if there isn't a RemoteException.
1638 } catch (RemoteException e) {
1639 throw new ImsException("addRegistrationCallback()", e,
1640 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1641 }
1642 }
1643
1644 public @ImsRegistrationImplBase.ImsRegistrationTech int getRegistrationTech() {
1645 try {
1646 return mMmTelFeatureConnection.getRegistrationTech();
1647 } catch (RemoteException e) {
1648 Log.w(TAG, "getRegistrationTech: no connection to ImsService.");
1649 return ImsRegistrationImplBase.REGISTRATION_TECH_NONE;
Brad Ebinger16780ff2017-01-26 11:18:21 -08001650 }
1651 }
1652
1653 /**
Brad Ebinger172977a2018-01-16 09:36:56 -08001654 * Closes the connection and removes all active callbacks.
Wink Savilleef36ef62014-06-11 08:39:38 -07001655 * All the resources that were allocated to the service are also released.
Wink Savilleef36ef62014-06-11 08:39:38 -07001656 */
Brad Ebinger172977a2018-01-16 09:36:56 -08001657 public void close() {
1658 if (mMmTelFeatureConnection != null) {
1659 mMmTelFeatureConnection.closeConnection();
Wink Savilleef36ef62014-06-11 08:39:38 -07001660 }
Brad Ebinger172977a2018-01-16 09:36:56 -08001661 mUt = null;
1662 mConfig = null;
1663 mEcbm = null;
1664 mMultiEndpoint = null;
Wink Savilleef36ef62014-06-11 08:39:38 -07001665 }
1666
1667 /**
1668 * Gets the configuration interface to provision / withdraw the supplementary service settings.
1669 *
Wink Savilleef36ef62014-06-11 08:39:38 -07001670 * @return the Ut interface instance
1671 * @throws ImsException if getting the Ut interface results in an error
1672 */
Brad Ebinger172977a2018-01-16 09:36:56 -08001673 public ImsUtInterface getSupplementaryServiceConfiguration() throws ImsException {
Brad Ebinger16780ff2017-01-26 11:18:21 -08001674 // FIXME: manage the multiple Ut interfaces based on the session id
Brad Ebinger138b4a62017-06-20 16:29:50 -07001675 if (mUt != null && mUt.isBinderAlive()) {
1676 return mUt;
Wink Savilleef36ef62014-06-11 08:39:38 -07001677 }
1678
Brad Ebinger138b4a62017-06-20 16:29:50 -07001679 checkAndThrowExceptionIfServiceUnavailable();
1680 try {
Brad Ebinger172977a2018-01-16 09:36:56 -08001681 IImsUt iUt = mMmTelFeatureConnection.getUtInterface();
Brad Ebinger138b4a62017-06-20 16:29:50 -07001682
1683 if (iUt == null) {
1684 throw new ImsException("getSupplementaryServiceConfiguration()",
1685 ImsReasonInfo.CODE_UT_NOT_SUPPORTED);
1686 }
1687
1688 mUt = new ImsUt(iUt);
1689 } catch (RemoteException e) {
1690 throw new ImsException("getSupplementaryServiceConfiguration()", e,
1691 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1692 }
Wink Savilleef36ef62014-06-11 08:39:38 -07001693 return mUt;
1694 }
1695
1696 /**
Wink Savilleef36ef62014-06-11 08:39:38 -07001697 * Creates a {@link ImsCallProfile} from the service capabilities & IMS registration state.
1698 *
Wink Savilleef36ef62014-06-11 08:39:38 -07001699 * @param serviceType a service type that is specified in {@link ImsCallProfile}
1700 * {@link ImsCallProfile#SERVICE_TYPE_NONE}
1701 * {@link ImsCallProfile#SERVICE_TYPE_NORMAL}
1702 * {@link ImsCallProfile#SERVICE_TYPE_EMERGENCY}
1703 * @param callType a call type that is specified in {@link ImsCallProfile}
1704 * {@link ImsCallProfile#CALL_TYPE_VOICE}
1705 * {@link ImsCallProfile#CALL_TYPE_VT}
1706 * {@link ImsCallProfile#CALL_TYPE_VT_TX}
1707 * {@link ImsCallProfile#CALL_TYPE_VT_RX}
1708 * {@link ImsCallProfile#CALL_TYPE_VT_NODIR}
1709 * {@link ImsCallProfile#CALL_TYPE_VS}
1710 * {@link ImsCallProfile#CALL_TYPE_VS_TX}
1711 * {@link ImsCallProfile#CALL_TYPE_VS_RX}
1712 * @return a {@link ImsCallProfile} object
1713 * @throws ImsException if calling the IMS service results in an error
1714 */
Brad Ebinger172977a2018-01-16 09:36:56 -08001715 public ImsCallProfile createCallProfile(int serviceType, int callType) throws ImsException {
Wink Savilleef36ef62014-06-11 08:39:38 -07001716 checkAndThrowExceptionIfServiceUnavailable();
1717
1718 try {
Brad Ebinger172977a2018-01-16 09:36:56 -08001719 return mMmTelFeatureConnection.createCallProfile(serviceType, callType);
Wink Savilleef36ef62014-06-11 08:39:38 -07001720 } catch (RemoteException e) {
1721 throw new ImsException("createCallProfile()", e,
1722 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1723 }
1724 }
1725
1726 /**
1727 * Creates a {@link ImsCall} to make a call.
1728 *
Wink Savilleef36ef62014-06-11 08:39:38 -07001729 * @param profile a call profile to make the call
1730 * (it contains service type, call type, media information, etc.)
Brad Ebinger172977a2018-01-16 09:36:56 -08001731 * @param callees participants to invite the conference call
Wink Savilleef36ef62014-06-11 08:39:38 -07001732 * @param listener listen to the call events from {@link ImsCall}
1733 * @return a {@link ImsCall} object
1734 * @throws ImsException if calling the IMS service results in an error
1735 */
Brad Ebinger172977a2018-01-16 09:36:56 -08001736 public ImsCall makeCall(ImsCallProfile profile, String[] callees,
Wink Savilleef36ef62014-06-11 08:39:38 -07001737 ImsCall.Listener listener) throws ImsException {
1738 if (DBG) {
Brad Ebinger172977a2018-01-16 09:36:56 -08001739 log("makeCall :: profile=" + profile);
Wink Savilleef36ef62014-06-11 08:39:38 -07001740 }
1741
1742 checkAndThrowExceptionIfServiceUnavailable();
1743
1744 ImsCall call = new ImsCall(mContext, profile);
1745
1746 call.setListener(listener);
Brad Ebinger172977a2018-01-16 09:36:56 -08001747 ImsCallSession session = createCallSession(profile);
Wink Savilleef36ef62014-06-11 08:39:38 -07001748
1749 if ((callees != null) && (callees.length == 1)) {
1750 call.start(session, callees[0]);
1751 } else {
1752 call.start(session, callees);
1753 }
1754
1755 return call;
1756 }
1757
1758 /**
1759 * Creates a {@link ImsCall} to take an incoming call.
1760 *
Brad Ebinger16780ff2017-01-26 11:18:21 -08001761 * @param sessionId a session id which is obtained from {@link ImsManager#open}
Brad Ebinger172977a2018-01-16 09:36:56 -08001762 * @param incomingCallExtras the incoming call broadcast intent
Wink Savilleef36ef62014-06-11 08:39:38 -07001763 * @param listener to listen to the call events from {@link ImsCall}
1764 * @return a {@link ImsCall} object
1765 * @throws ImsException if calling the IMS service results in an error
1766 */
Brad Ebinger172977a2018-01-16 09:36:56 -08001767 public ImsCall takeCall(IImsCallSession session, Bundle incomingCallExtras,
Wink Savilleef36ef62014-06-11 08:39:38 -07001768 ImsCall.Listener listener) throws ImsException {
1769 if (DBG) {
Brad Ebinger172977a2018-01-16 09:36:56 -08001770 log("takeCall :: incomingCall=" + incomingCallExtras);
Wink Savilleef36ef62014-06-11 08:39:38 -07001771 }
1772
1773 checkAndThrowExceptionIfServiceUnavailable();
1774
Brad Ebinger172977a2018-01-16 09:36:56 -08001775 if (incomingCallExtras == null) {
Wink Savilleef36ef62014-06-11 08:39:38 -07001776 throw new ImsException("Can't retrieve session with null intent",
1777 ImsReasonInfo.CODE_LOCAL_ILLEGAL_ARGUMENT);
1778 }
1779
Brad Ebinger172977a2018-01-16 09:36:56 -08001780 String callId = getCallId(incomingCallExtras);
Wink Savilleef36ef62014-06-11 08:39:38 -07001781
1782 if (callId == null) {
1783 throw new ImsException("Call ID missing in the incoming call intent",
1784 ImsReasonInfo.CODE_LOCAL_ILLEGAL_ARGUMENT);
1785 }
1786
1787 try {
Wink Savilleef36ef62014-06-11 08:39:38 -07001788 if (session == null) {
1789 throw new ImsException("No pending session for the call",
1790 ImsReasonInfo.CODE_LOCAL_NO_PENDING_CALL);
1791 }
1792
1793 ImsCall call = new ImsCall(mContext, session.getCallProfile());
1794
1795 call.attachSession(new ImsCallSession(session));
1796 call.setListener(listener);
1797
1798 return call;
1799 } catch (Throwable t) {
1800 throw new ImsException("takeCall()", t, ImsReasonInfo.CODE_UNSPECIFIED);
1801 }
1802 }
1803
1804 /**
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -05001805 * Gets the config interface to get/set service/capability parameters.
1806 *
1807 * @return the ImsConfig instance.
1808 * @throws ImsException if getting the setting interface results in an error.
1809 */
1810 public ImsConfig getConfigInterface() throws ImsException {
Brad Ebinger138b4a62017-06-20 16:29:50 -07001811 if (mConfig != null && mConfig.isBinderAlive()) {
1812 return mConfig;
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -05001813 }
Brad Ebinger138b4a62017-06-20 16:29:50 -07001814
1815 checkAndThrowExceptionIfServiceUnavailable();
1816 try {
Brad Ebinger172977a2018-01-16 09:36:56 -08001817 IImsConfig config = mMmTelFeatureConnection.getConfigInterface();
Brad Ebinger138b4a62017-06-20 16:29:50 -07001818 if (config == null) {
1819 throw new ImsException("getConfigInterface()",
1820 ImsReasonInfo.CODE_LOCAL_SERVICE_UNAVAILABLE);
1821 }
1822 mConfig = new ImsConfig(config, mContext);
1823 } catch (RemoteException e) {
1824 throw new ImsException("getConfigInterface()", e,
1825 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1826 }
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -05001827 return mConfig;
1828 }
1829
Brad Ebinger172977a2018-01-16 09:36:56 -08001830 public void changeMmTelCapability(
1831 @MmTelFeature.MmTelCapabilities.MmTelCapability int capability,
1832 @ImsRegistrationImplBase.ImsRegistrationTech int radioTech,
1833 boolean isEnabled) throws RemoteException {
1834 CapabilityChangeRequest request = new CapabilityChangeRequest();
1835 if (isEnabled) {
1836 request.addCapabilitiesToEnableForTech(capability, radioTech);
1837 } else {
1838 request.addCapabilitiesToDisableForTech(capability, radioTech);
1839 }
1840 mMmTelFeatureConnection.changeEnabledCapabilities(request, null);
1841 if (mImsConfigListener != null) {
1842 mImsConfigListener.onSetFeatureResponse(capability,
1843 mMmTelFeatureConnection.getRegistrationTech(),
1844 isEnabled ? ImsConfig.FeatureValueConstants.ON
1845 : ImsConfig.FeatureValueConstants.OFF, -1);
1846 }
1847 }
1848
Hall Liub77d8972018-01-22 19:15:05 -08001849 public void setRttEnabled(boolean enabled) {
1850 try {
1851 setAdvanced4GMode(enabled || isEnhanced4gLteModeSettingEnabledByUser());
1852 final int value = enabled ? ImsConfig.FeatureValueConstants.ON :
1853 ImsConfig.FeatureValueConstants.OFF;
1854 Thread thread = new Thread(() -> {
1855 try {
1856 Log.i(ImsManager.class.getSimpleName(), "Setting RTT enabled to " + enabled);
1857 getConfigInterface().setProvisionedValue(
1858 ImsConfig.ConfigConstants.RTT_SETTING_ENABLED, value);
1859 } catch (ImsException e) {
1860 Log.e(ImsManager.class.getSimpleName(), "Unable to set RTT enabled to "
1861 + enabled + ": " + e);
1862 }
1863 });
1864 thread.start();
1865 } catch (ImsException e) {
1866 Log.e(ImsManager.class.getSimpleName(), "Unable to set RTT enabled to " + enabled
1867 + ": " + e);
1868 }
1869 }
1870
Hall Liue511a202017-08-17 15:49:58 -07001871 /**
1872 * Set the TTY mode. This is the actual tty mode (varies depending on peripheral status)
1873 */
1874 public void setTtyMode(int ttyMode) throws ImsException {
Brad Ebinger479f52c2017-08-28 13:19:22 -07001875 if (!getBooleanCarrierConfig(
Hall Liue511a202017-08-17 15:49:58 -07001876 CarrierConfigManager.KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL)) {
1877 setAdvanced4GMode((ttyMode == TelecomManager.TTY_MODE_OFF) &&
Brad Ebinger479f52c2017-08-28 13:19:22 -07001878 isEnhanced4gLteModeSettingEnabledByUser());
Hall Liue511a202017-08-17 15:49:58 -07001879 }
1880 }
1881
1882 /**
1883 * Sets the UI TTY mode. This is the preferred TTY mode that the user sets in the call
1884 * settings screen.
Brad Ebingerb19b2832018-04-11 11:27:50 -07001885 * @param uiTtyMode TTY Mode, valid options are:
1886 * - {@link com.android.internal.telephony.Phone#TTY_MODE_OFF}
1887 * - {@link com.android.internal.telephony.Phone#TTY_MODE_FULL}
1888 * - {@link com.android.internal.telephony.Phone#TTY_MODE_HCO}
1889 * - {@link com.android.internal.telephony.Phone#TTY_MODE_VCO}
1890 * @param onComplete A Message that will be called by the ImsService when it has completed this
1891 * operation or null if not waiting for an async response. The Message must contain a
1892 * valid {@link Message#replyTo} {@link android.os.Messenger}, since it will be passed
1893 * through Binder to another process.
Hall Liue511a202017-08-17 15:49:58 -07001894 */
Brad Ebingerb5f30c72017-02-17 14:54:31 -08001895 public void setUiTTYMode(Context context, int uiTtyMode, Message onComplete)
Shriram Ganeshc403b7b2014-08-14 14:18:57 +05301896 throws ImsException {
1897
Etan Cohen82f78122014-12-15 10:10:14 -08001898 checkAndThrowExceptionIfServiceUnavailable();
Shriram Ganeshc403b7b2014-08-14 14:18:57 +05301899
Etan Cohen82f78122014-12-15 10:10:14 -08001900 try {
Brad Ebinger172977a2018-01-16 09:36:56 -08001901 mMmTelFeatureConnection.setUiTTYMode(uiTtyMode, onComplete);
Etan Cohen82f78122014-12-15 10:10:14 -08001902 } catch (RemoteException e) {
1903 throw new ImsException("setTTYMode()", e,
1904 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1905 }
Shriram Ganeshc403b7b2014-08-14 14:18:57 +05301906 }
1907
Naveen Kalla525c3a22017-02-06 14:46:42 -08001908 private ImsReasonInfo makeACopy(ImsReasonInfo imsReasonInfo) {
1909 Parcel p = Parcel.obtain();
1910 imsReasonInfo.writeToParcel(p, 0);
1911 p.setDataPosition(0);
1912 ImsReasonInfo clonedReasonInfo = ImsReasonInfo.CREATOR.createFromParcel(p);
1913 p.recycle();
1914 return clonedReasonInfo;
1915 }
1916
1917 /**
1918 * Get Recent IMS Disconnect Reasons.
1919 *
1920 * @return ArrayList of ImsReasonInfo objects. MAX size of the arraylist
1921 * is MAX_RECENT_DISCONNECT_REASONS. The objects are in the
1922 * chronological order.
1923 */
1924 public ArrayList<ImsReasonInfo> getRecentImsDisconnectReasons() {
1925 ArrayList<ImsReasonInfo> disconnectReasons = new ArrayList<>();
1926
1927 for (ImsReasonInfo reason : mRecentDisconnectReasons) {
1928 disconnectReasons.add(makeACopy(reason));
1929 }
1930 return disconnectReasons;
1931 }
Brad Ebinger16417b42017-03-07 13:48:50 -08001932
Brad Ebinger172977a2018-01-16 09:36:56 -08001933 public int getImsServiceState() throws ImsException {
1934 return mMmTelFeatureConnection.getFeatureState();
Brad Ebinger16780ff2017-01-26 11:18:21 -08001935 }
Naveen Kalla525c3a22017-02-06 14:46:42 -08001936
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -05001937 /**
Junda Liue7663c02015-06-23 11:16:26 -07001938 * Get the boolean config from carrier config manager.
1939 *
Brad Ebinger16417b42017-03-07 13:48:50 -08001940 * @param key config key defined in CarrierConfigManager
1941 * @return boolean value of corresponding key.
1942 */
Brad Ebinger479f52c2017-08-28 13:19:22 -07001943 private boolean getBooleanCarrierConfig(String key) {
Brad Ebinger16417b42017-03-07 13:48:50 -08001944 int[] subIds = SubscriptionManager.getSubId(mPhoneId);
1945 int subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1946 if (subIds != null && subIds.length >= 1) {
1947 subId = subIds[0];
1948 }
1949 PersistableBundle b = null;
1950 if (mConfigManager != null) {
1951 // If an invalid subId is used, this bundle will contain default values.
1952 b = mConfigManager.getConfigForSubId(subId);
1953 }
1954 if (b != null) {
1955 return b.getBoolean(key);
1956 } else {
1957 // Return static default defined in CarrierConfigManager.
1958 return CarrierConfigManager.getDefaultConfig().getBoolean(key);
1959 }
1960 }
1961
1962 /**
fionaxu5803ef02016-03-08 11:48:48 -08001963 * Get the int config from carrier config manager.
1964 *
Brad Ebinger16417b42017-03-07 13:48:50 -08001965 * @param key config key defined in CarrierConfigManager
1966 * @return integer value of corresponding key.
1967 */
Brad Ebinger479f52c2017-08-28 13:19:22 -07001968 private int getIntCarrierConfig(String key) {
Brad Ebinger16417b42017-03-07 13:48:50 -08001969 int[] subIds = SubscriptionManager.getSubId(mPhoneId);
1970 int subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1971 if (subIds != null && subIds.length >= 1) {
1972 subId = subIds[0];
1973 }
1974 PersistableBundle b = null;
1975 if (mConfigManager != null) {
1976 // If an invalid subId is used, this bundle will contain default values.
1977 b = mConfigManager.getConfigForSubId(subId);
1978 }
1979 if (b != null) {
1980 return b.getInt(key);
1981 } else {
1982 // Return static default defined in CarrierConfigManager.
1983 return CarrierConfigManager.getDefaultConfig().getInt(key);
1984 }
1985 }
1986
1987 /**
Wink Savilleef36ef62014-06-11 08:39:38 -07001988 * Gets the call ID from the specified incoming call broadcast intent.
1989 *
Brad Ebinger172977a2018-01-16 09:36:56 -08001990 * @param incomingCallExtras the incoming call broadcast intent
Wink Savilleef36ef62014-06-11 08:39:38 -07001991 * @return the call ID or null if the intent does not contain it
1992 */
Brad Ebinger172977a2018-01-16 09:36:56 -08001993 private static String getCallId(Bundle incomingCallExtras) {
1994 if (incomingCallExtras == null) {
Wink Savilleef36ef62014-06-11 08:39:38 -07001995 return null;
1996 }
1997
Brad Ebinger172977a2018-01-16 09:36:56 -08001998 return incomingCallExtras.getString(EXTRA_CALL_ID);
Wink Savilleef36ef62014-06-11 08:39:38 -07001999 }
2000
2001 /**
Brad Ebingerb10b61e2017-04-18 11:45:26 -07002002 * Checks to see if the ImsService Binder is connected. If it is not, we try to create the
2003 * connection again.
Wink Savilleef36ef62014-06-11 08:39:38 -07002004 */
2005 private void checkAndThrowExceptionIfServiceUnavailable()
2006 throws ImsException {
Brad Ebinger172977a2018-01-16 09:36:56 -08002007 if (mMmTelFeatureConnection == null || !mMmTelFeatureConnection.isBinderAlive()) {
Brad Ebinger16780ff2017-01-26 11:18:21 -08002008 createImsService();
Wink Savilleef36ef62014-06-11 08:39:38 -07002009
Brad Ebinger172977a2018-01-16 09:36:56 -08002010 if (mMmTelFeatureConnection == null) {
Wink Savilleef36ef62014-06-11 08:39:38 -07002011 throw new ImsException("Service is unavailable",
2012 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
2013 }
2014 }
2015 }
2016
Brad Ebinger16780ff2017-01-26 11:18:21 -08002017 /**
2018 * Binds the IMS service to make/receive the call. Supports two methods of exposing an
2019 * ImsService:
2020 * 1) com.android.ims.ImsService implementation in ServiceManager (deprecated).
2021 * 2) android.telephony.ims.ImsService implementation through ImsResolver.
2022 */
2023 private void createImsService() {
Brad Ebinger172977a2018-01-16 09:36:56 -08002024 Rlog.i(TAG, "Creating ImsService");
2025 mMmTelFeatureConnection = MmTelFeatureConnection.create(mContext, mPhoneId);
2026
Brad Ebinger44fd8af2017-12-14 14:24:02 -08002027 // Forwarding interface to tell mStatusCallbacks that the Proxy is unavailable.
Brad Ebinger172977a2018-01-16 09:36:56 -08002028 mMmTelFeatureConnection.setStatusCallback(new MmTelFeatureConnection.IFeatureUpdate() {
Brad Ebinger44fd8af2017-12-14 14:24:02 -08002029 @Override
2030 public void notifyStateChanged() {
Brad Ebinger172977a2018-01-16 09:36:56 -08002031 mStatusCallbacks.forEach(MmTelFeatureConnection.IFeatureUpdate::notifyStateChanged);
Brad Ebinger44fd8af2017-12-14 14:24:02 -08002032 }
2033
2034 @Override
2035 public void notifyUnavailable() {
Brad Ebinger172977a2018-01-16 09:36:56 -08002036 mStatusCallbacks.forEach(MmTelFeatureConnection.IFeatureUpdate::notifyUnavailable);
Brad Ebinger44fd8af2017-12-14 14:24:02 -08002037 }
2038 });
Etan Cohend7727462014-07-12 14:54:10 -07002039 }
2040
Wink Savilleef36ef62014-06-11 08:39:38 -07002041 /**
2042 * Creates a {@link ImsCallSession} with the specified call profile.
2043 * Use other methods, if applicable, instead of interacting with
2044 * {@link ImsCallSession} directly.
2045 *
Wink Savilleef36ef62014-06-11 08:39:38 -07002046 * @param profile a call profile to make the call
2047 */
Brad Ebinger172977a2018-01-16 09:36:56 -08002048 private ImsCallSession createCallSession(ImsCallProfile profile) throws ImsException {
Wink Savilleef36ef62014-06-11 08:39:38 -07002049 try {
Brad Ebingerb10b61e2017-04-18 11:45:26 -07002050 // Throws an exception if the ImsService Feature is not ready to accept commands.
Brad Ebinger172977a2018-01-16 09:36:56 -08002051 return new ImsCallSession(mMmTelFeatureConnection.createCallSession(profile));
Wink Savilleef36ef62014-06-11 08:39:38 -07002052 } catch (RemoteException e) {
Brad Ebingerb10b61e2017-04-18 11:45:26 -07002053 Rlog.w(TAG, "CreateCallSession: Error, remote exception: " + e.getMessage());
2054 throw new ImsException("createCallSession()", e,
2055 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
2056
Wink Savilleef36ef62014-06-11 08:39:38 -07002057 }
2058 }
2059
Etan Cohena00c9192014-12-23 15:02:29 -08002060 private static void log(String s) {
Wink Savilleef36ef62014-06-11 08:39:38 -07002061 Rlog.d(TAG, s);
2062 }
2063
Etan Cohena00c9192014-12-23 15:02:29 -08002064 private static void loge(String s) {
Wink Savilleef36ef62014-06-11 08:39:38 -07002065 Rlog.e(TAG, s);
2066 }
2067
Etan Cohena00c9192014-12-23 15:02:29 -08002068 private static void loge(String s, Throwable t) {
Wink Savilleef36ef62014-06-11 08:39:38 -07002069 Rlog.e(TAG, s, t);
2070 }
2071
2072 /**
ram7da5a112014-07-16 20:59:27 +05302073 * Used for turning on IMS.if its off already
2074 */
Etan Cohen82f78122014-12-15 10:10:14 -08002075 private void turnOnIms() throws ImsException {
Brad Ebinger172977a2018-01-16 09:36:56 -08002076 TelephonyManager tm = (TelephonyManager)
2077 mContext.getSystemService(Context.TELEPHONY_SERVICE);
2078 tm.enableIms(mPhoneId);
ram7da5a112014-07-16 20:59:27 +05302079 }
2080
Omkar Kolangade75f3ca32014-10-24 11:10:52 -07002081 private boolean isImsTurnOffAllowed() {
Brad Ebinger479f52c2017-08-28 13:19:22 -07002082 return isTurnOffImsAllowedByPlatform()
2083 && (!isWfcEnabledByPlatform()
2084 || !isWfcEnabledByUser());
Omkar Kolangade75f3ca32014-10-24 11:10:52 -07002085 }
2086
Amit Mahajan9cba36d2016-08-11 10:17:23 -07002087 private void setLteFeatureValues(boolean turnOn) {
2088 log("setLteFeatureValues: " + turnOn);
Brad Ebinger172977a2018-01-16 09:36:56 -08002089 CapabilityChangeRequest request = new CapabilityChangeRequest();
2090 if (turnOn) {
2091 request.addCapabilitiesToEnableForTech(
2092 MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE,
2093 ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
2094 } else {
2095 request.addCapabilitiesToDisableForTech(
2096 MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE,
2097 ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
2098 }
Pavel Zhamaitsiakff29b9d2016-04-15 12:16:57 -07002099
Brad Ebinger172977a2018-01-16 09:36:56 -08002100 if (isVolteEnabledByPlatform()) {
2101 boolean ignoreDataEnabledChanged = getBooleanCarrierConfig(
2102 CarrierConfigManager.KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS);
2103 boolean enableViLte = turnOn && isVtEnabledByUser() &&
2104 (ignoreDataEnabledChanged || isDataEnabled());
2105 if (enableViLte) {
2106 request.addCapabilitiesToEnableForTech(
2107 MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VIDEO,
2108 ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
2109 } else {
2110 request.addCapabilitiesToDisableForTech(
2111 MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VIDEO,
2112 ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
Etan Cohenb651fa52014-10-22 10:51:29 -07002113 }
Brad Ebinger172977a2018-01-16 09:36:56 -08002114 }
2115 try {
2116 mMmTelFeatureConnection.changeEnabledCapabilities(request, null);
2117 } catch (RemoteException e) {
2118 Log.e(TAG, "setLteFeatureValues: Exception: " + e.getMessage());
Etan Cohencfc784d2014-08-07 18:40:31 -07002119 }
Amit Mahajan9cba36d2016-08-11 10:17:23 -07002120 }
2121
2122 private void setAdvanced4GMode(boolean turnOn) throws ImsException {
2123 checkAndThrowExceptionIfServiceUnavailable();
2124
2125 // if turnOn: first set feature values then call turnOnIms()
2126 // if turnOff: only set feature values if IMS turn off is not allowed. If turn off is
2127 // allowed, first call turnOffIms() then set feature values
Etan Cohencfc784d2014-08-07 18:40:31 -07002128 if (turnOn) {
Amit Mahajan9cba36d2016-08-11 10:17:23 -07002129 setLteFeatureValues(turnOn);
2130 log("setAdvanced4GMode: turnOnIms");
Etan Cohencfc784d2014-08-07 18:40:31 -07002131 turnOnIms();
Amit Mahajan9cba36d2016-08-11 10:17:23 -07002132 } else {
2133 if (isImsTurnOffAllowed()) {
2134 log("setAdvanced4GMode: turnOffIms");
2135 turnOffIms();
2136 }
2137 setLteFeatureValues(turnOn);
Etan Cohencfc784d2014-08-07 18:40:31 -07002138 }
2139 }
2140
ram7da5a112014-07-16 20:59:27 +05302141 /**
2142 * Used for turning off IMS completely in order to make the device CSFB'ed.
2143 * Once turned off, all calls will be over CS.
2144 */
Etan Cohen82f78122014-12-15 10:10:14 -08002145 private void turnOffIms() throws ImsException {
Brad Ebinger172977a2018-01-16 09:36:56 -08002146 TelephonyManager tm = (TelephonyManager)
2147 mContext.getSystemService(Context.TELEPHONY_SERVICE);
2148 tm.disableIms(mPhoneId);
ram7da5a112014-07-16 20:59:27 +05302149 }
2150
Naveen Kalla525c3a22017-02-06 14:46:42 -08002151 private void addToRecentDisconnectReasons(ImsReasonInfo reason) {
2152 if (reason == null) return;
2153 while (mRecentDisconnectReasons.size() >= MAX_RECENT_DISCONNECT_REASONS) {
2154 mRecentDisconnectReasons.removeFirst();
2155 }
2156 mRecentDisconnectReasons.addLast(reason);
2157 }
2158
ram7da5a112014-07-16 20:59:27 +05302159 /**
Wink Savilleef36ef62014-06-11 08:39:38 -07002160 * Death recipient class for monitoring IMS service.
2161 */
2162 private class ImsServiceDeathRecipient implements IBinder.DeathRecipient {
2163 @Override
2164 public void binderDied() {
Brad Ebinger172977a2018-01-16 09:36:56 -08002165 mMmTelFeatureConnection = null;
Wink Savilleef36ef62014-06-11 08:39:38 -07002166 mUt = null;
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -05002167 mConfig = null;
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -07002168 mEcbm = null;
Tyler Gunn4d128b62016-04-13 15:44:38 -07002169 mMultiEndpoint = null;
Wink Savilleef36ef62014-06-11 08:39:38 -07002170 }
2171 }
2172
2173 /**
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -07002174 * Gets the ECBM interface to request ECBM exit.
2175 *
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -07002176 * @return the ECBM interface instance
2177 * @throws ImsException if getting the ECBM interface results in an error
2178 */
Brad Ebinger172977a2018-01-16 09:36:56 -08002179 public ImsEcbm getEcbmInterface() throws ImsException {
Brad Ebinger138b4a62017-06-20 16:29:50 -07002180 if (mEcbm != null && mEcbm.isBinderAlive()) {
2181 return mEcbm;
2182 }
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -07002183
Brad Ebinger138b4a62017-06-20 16:29:50 -07002184 checkAndThrowExceptionIfServiceUnavailable();
2185 try {
Brad Ebinger172977a2018-01-16 09:36:56 -08002186 IImsEcbm iEcbm = mMmTelFeatureConnection.getEcbmInterface();
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -07002187
Brad Ebinger138b4a62017-06-20 16:29:50 -07002188 if (iEcbm == null) {
2189 throw new ImsException("getEcbmInterface()",
2190 ImsReasonInfo.CODE_ECBM_NOT_SUPPORTED);
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -07002191 }
Brad Ebinger138b4a62017-06-20 16:29:50 -07002192 mEcbm = new ImsEcbm(iEcbm);
2193 } catch (RemoteException e) {
2194 throw new ImsException("getEcbmInterface()", e,
2195 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -07002196 }
2197 return mEcbm;
2198 }
Pavel Zhamaitsiak8c065f52015-11-10 14:36:44 -08002199
Mohamed Abdalkader4d68a982018-01-10 13:29:26 -08002200 public void sendSms(int token, int messageRef, String format, String smsc, boolean isRetry,
2201 byte[] pdu) throws ImsException {
2202 try {
Brad Ebinger172977a2018-01-16 09:36:56 -08002203 mMmTelFeatureConnection.sendSms(token, messageRef, format, smsc, isRetry, pdu);
Mohamed Abdalkader4d68a982018-01-10 13:29:26 -08002204 } catch (RemoteException e) {
2205 throw new ImsException("sendSms()", e, ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
2206 }
2207 }
2208
2209 public void acknowledgeSms(int token, int messageRef, int result) throws ImsException {
2210 try {
Brad Ebinger172977a2018-01-16 09:36:56 -08002211 mMmTelFeatureConnection.acknowledgeSms(token, messageRef, result);
Mohamed Abdalkader4d68a982018-01-10 13:29:26 -08002212 } catch (RemoteException e) {
2213 throw new ImsException("acknowledgeSms()", e,
2214 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
2215 }
2216 }
2217
2218 public void acknowledgeSmsReport(int token, int messageRef, int result) throws ImsException{
2219 try {
Brad Ebinger172977a2018-01-16 09:36:56 -08002220 mMmTelFeatureConnection.acknowledgeSmsReport(token, messageRef, result);
Mohamed Abdalkader4d68a982018-01-10 13:29:26 -08002221 } catch (RemoteException e) {
2222 throw new ImsException("acknowledgeSmsReport()", e,
2223 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
2224 }
2225 }
2226
2227 public String getSmsFormat() throws ImsException{
2228 try {
Brad Ebinger172977a2018-01-16 09:36:56 -08002229 return mMmTelFeatureConnection.getSmsFormat();
Mohamed Abdalkader4d68a982018-01-10 13:29:26 -08002230 } catch (RemoteException e) {
2231 throw new ImsException("getSmsFormat()", e,
2232 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
2233 }
2234 }
2235
2236 public void setSmsListener(IImsSmsListener listener) throws ImsException {
2237 try {
Brad Ebinger172977a2018-01-16 09:36:56 -08002238 mMmTelFeatureConnection.setSmsListener(listener);
Mohamed Abdalkader4d68a982018-01-10 13:29:26 -08002239 } catch (RemoteException e) {
2240 throw new ImsException("setSmsListener()", e,
2241 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
2242 }
2243 }
Mohamed Abdalkadere1453f42018-01-19 19:48:31 -08002244
Brad Ebingerd449b232018-02-12 14:33:05 -08002245 public void onSmsReady() throws ImsException {
Mohamed Abdalkader0e734e12018-01-23 13:11:00 -08002246 try {
Brad Ebinger190ed932018-01-23 13:41:32 -08002247 mMmTelFeatureConnection.onSmsReady();
Mohamed Abdalkader0e734e12018-01-23 13:11:00 -08002248 } catch (RemoteException e) {
2249 throw new ImsException("onSmsReady()", e,
2250 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
2251 }
2252 }
2253
Pavel Zhamaitsiak8c065f52015-11-10 14:36:44 -08002254 /**
Brad Ebingerd449b232018-02-12 14:33:05 -08002255 * Determines whether or not a call with the specified numbers should be placed over IMS or over
2256 * CSFB.
2257 * @param isEmergency is at least one call an emergency number.
2258 * @param numbers A {@link String} array containing the numbers in the call being placed. Can
2259 * be multiple numbers in the case of dialing out a conference.
2260 * @return The result of the query, one of the following values:
2261 * - {@link MmTelFeature#PROCESS_CALL_IMS}
2262 * - {@link MmTelFeature#PROCESS_CALL_CSFB}
2263 * @throws ImsException if the ImsService is not available. In this case, we should fall back
2264 * to CSFB anyway.
2265 */
2266 public @MmTelFeature.ProcessCallResult int shouldProcessCall(boolean isEmergency,
2267 String[] numbers) throws ImsException {
2268 try {
2269 return mMmTelFeatureConnection.shouldProcessCall(isEmergency, numbers);
2270 } catch (RemoteException e) {
2271 throw new ImsException("shouldProcessCall()", e,
2272 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
2273 }
2274 }
2275
2276 /**
Tyler Gunn4d128b62016-04-13 15:44:38 -07002277 * Gets the Multi-Endpoint interface to subscribe to multi-enpoint notifications..
2278 *
Tyler Gunn4d128b62016-04-13 15:44:38 -07002279 * @return the multi-endpoint interface instance
2280 * @throws ImsException if getting the multi-endpoint interface results in an error
2281 */
Brad Ebinger172977a2018-01-16 09:36:56 -08002282 public ImsMultiEndpoint getMultiEndpointInterface() throws ImsException {
Brad Ebinger138b4a62017-06-20 16:29:50 -07002283 if (mMultiEndpoint != null && mMultiEndpoint.isBinderAlive()) {
2284 return mMultiEndpoint;
Tyler Gunn4d128b62016-04-13 15:44:38 -07002285 }
Brad Ebinger138b4a62017-06-20 16:29:50 -07002286
2287 checkAndThrowExceptionIfServiceUnavailable();
2288 try {
Brad Ebinger172977a2018-01-16 09:36:56 -08002289 IImsMultiEndpoint iImsMultiEndpoint = mMmTelFeatureConnection.getMultiEndpointInterface();
Brad Ebinger138b4a62017-06-20 16:29:50 -07002290
2291 if (iImsMultiEndpoint == null) {
2292 throw new ImsException("getMultiEndpointInterface()",
2293 ImsReasonInfo.CODE_MULTIENDPOINT_NOT_SUPPORTED);
2294 }
2295 mMultiEndpoint = new ImsMultiEndpoint(iImsMultiEndpoint);
2296 } catch (RemoteException e) {
2297 throw new ImsException("getMultiEndpointInterface()", e,
2298 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
2299 }
2300
Tyler Gunn4d128b62016-04-13 15:44:38 -07002301 return mMultiEndpoint;
2302 }
2303
2304 /**
Pavel Zhamaitsiak8c065f52015-11-10 14:36:44 -08002305 * Resets ImsManager settings back to factory defaults.
2306 *
Brad Ebinger479f52c2017-08-28 13:19:22 -07002307 * @deprecated Doesn't support MSIM devices. Use {@link #factoryReset()} instead.
Brad Ebinger16417b42017-03-07 13:48:50 -08002308 *
Pavel Zhamaitsiak8c065f52015-11-10 14:36:44 -08002309 * @hide
2310 */
2311 public static void factoryReset(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -07002312 ImsManager mgr = ImsManager.getInstance(context,
2313 SubscriptionManager.getDefaultVoicePhoneId());
2314 if (mgr != null) {
2315 mgr.factoryReset();
2316 }
2317 loge("factoryReset: ImsManager null.");
Pavel Zhamaitsiak8c065f52015-11-10 14:36:44 -08002318 }
Jack Yu2f102bd2015-12-28 15:31:48 -08002319
Brad Ebinger16417b42017-03-07 13:48:50 -08002320 /**
2321 * Resets ImsManager settings back to factory defaults.
2322 *
2323 * @hide
2324 */
Brad Ebinger479f52c2017-08-28 13:19:22 -07002325 public void factoryReset() {
Brad Ebinger16417b42017-03-07 13:48:50 -08002326 // Set VoLTE to default
Malcolm Chen212ca652017-09-28 17:28:45 -07002327 SubscriptionManager.setSubscriptionProperty(getSubId(),
manabu, shimoda96aee542017-10-06 15:39:36 +09002328 SubscriptionManager.ENHANCED_4G_MODE_ENABLED,
2329 booleanToPropertyString(getBooleanCarrierConfig(
2330 CarrierConfigManager.KEY_ENHANCED_4G_LTE_ON_BY_DEFAULT_BOOL)));
Brad Ebinger16417b42017-03-07 13:48:50 -08002331
2332 // Set VoWiFi to default
Malcolm Chen212ca652017-09-28 17:28:45 -07002333 SubscriptionManager.setSubscriptionProperty(getSubId(),
2334 SubscriptionManager.WFC_IMS_ENABLED,
2335 booleanToPropertyString(getBooleanCarrierConfig(
2336 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ENABLED_BOOL)));
Brad Ebinger16417b42017-03-07 13:48:50 -08002337
2338 // Set VoWiFi mode to default
Malcolm Chen212ca652017-09-28 17:28:45 -07002339 SubscriptionManager.setSubscriptionProperty(getSubId(),
2340 SubscriptionManager.WFC_IMS_MODE,
2341 Integer.toString(getIntCarrierConfig(
2342 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_MODE_INT)));
Brad Ebinger16417b42017-03-07 13:48:50 -08002343
2344 // Set VoWiFi roaming to default
Malcolm Chen212ca652017-09-28 17:28:45 -07002345 SubscriptionManager.setSubscriptionProperty(getSubId(),
2346 SubscriptionManager.WFC_IMS_ROAMING_ENABLED,
2347 booleanToPropertyString(getBooleanCarrierConfig(
2348 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_ENABLED_BOOL)));
Brad Ebinger16417b42017-03-07 13:48:50 -08002349
2350 // Set VT to default
Malcolm Chen212ca652017-09-28 17:28:45 -07002351 SubscriptionManager.setSubscriptionProperty(getSubId(),
2352 SubscriptionManager.VT_IMS_ENABLED, booleanToPropertyString(true));
Brad Ebinger16417b42017-03-07 13:48:50 -08002353
2354 // Push settings to ImsConfig
Brad Ebinger479f52c2017-08-28 13:19:22 -07002355 updateImsServiceConfig(true);
Brad Ebinger16417b42017-03-07 13:48:50 -08002356 }
2357
Amit Mahajan24f7b162016-07-21 16:33:53 -07002358 private boolean isDataEnabled() {
Malcolm Chenb8cd4402018-03-23 18:51:51 -07002359 return new TelephonyManager(mContext, getSubId()).isDataCapable();
Amit Mahajan24f7b162016-07-21 16:33:53 -07002360 }
2361
2362 private boolean isVolteProvisioned() {
Malcolm Chen18837ff2017-10-25 17:05:41 -07002363 return getProvisionedBoolNoException(
2364 ImsConfig.ConfigConstants.VLT_SETTING_ENABLED);
Amit Mahajan24f7b162016-07-21 16:33:53 -07002365 }
2366
2367 private boolean isWfcProvisioned() {
Malcolm Chen18837ff2017-10-25 17:05:41 -07002368 return getProvisionedBoolNoException(
2369 ImsConfig.ConfigConstants.VOICE_OVER_WIFI_SETTING_ENABLED);
Amit Mahajan24f7b162016-07-21 16:33:53 -07002370 }
2371
2372 private boolean isVtProvisioned() {
Malcolm Chen18837ff2017-10-25 17:05:41 -07002373 return getProvisionedBoolNoException(
2374 ImsConfig.ConfigConstants.LVC_SETTING_ENABLED);
Jack Yu643ffe42016-07-08 14:25:46 -07002375 }
2376
Malcolm Chen212ca652017-09-28 17:28:45 -07002377 private static String booleanToPropertyString(boolean bool) {
2378 return bool ? "1" : "0";
2379 }
2380
2381
Jack Yu2f102bd2015-12-28 15:31:48 -08002382 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
2383 pw.println("ImsManager:");
2384 pw.println(" mPhoneId = " + mPhoneId);
2385 pw.println(" mConfigUpdated = " + mConfigUpdated);
Brad Ebinger172977a2018-01-16 09:36:56 -08002386 pw.println(" mImsServiceProxy = " + mMmTelFeatureConnection);
Amit Mahajan24f7b162016-07-21 16:33:53 -07002387 pw.println(" mDataEnabled = " + isDataEnabled());
Brad Ebinger479f52c2017-08-28 13:19:22 -07002388 pw.println(" ignoreDataEnabledChanged = " + getBooleanCarrierConfig(
Jack Yu57781852016-11-16 17:20:38 -08002389 CarrierConfigManager.KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS));
Jack Yu2f102bd2015-12-28 15:31:48 -08002390
Brad Ebinger479f52c2017-08-28 13:19:22 -07002391 pw.println(" isGbaValid = " + isGbaValid());
Jack Yu2f102bd2015-12-28 15:31:48 -08002392 pw.println(" isImsTurnOffAllowed = " + isImsTurnOffAllowed());
Brad Ebinger479f52c2017-08-28 13:19:22 -07002393 pw.println(" isNonTtyOrTtyOnVolteEnabled = " + isNonTtyOrTtyOnVolteEnabled());
Jack Yu2f102bd2015-12-28 15:31:48 -08002394
Brad Ebinger479f52c2017-08-28 13:19:22 -07002395 pw.println(" isVolteEnabledByPlatform = " + isVolteEnabledByPlatform());
2396 pw.println(" isVolteProvisionedOnDevice = " + isVolteProvisionedOnDevice());
Jack Yu2f102bd2015-12-28 15:31:48 -08002397 pw.println(" isEnhanced4gLteModeSettingEnabledByUser = " +
Brad Ebinger479f52c2017-08-28 13:19:22 -07002398 isEnhanced4gLteModeSettingEnabledByUser());
2399 pw.println(" isVtEnabledByPlatform = " + isVtEnabledByPlatform());
2400 pw.println(" isVtEnabledByUser = " + isVtEnabledByUser());
Jack Yu2f102bd2015-12-28 15:31:48 -08002401
Brad Ebinger479f52c2017-08-28 13:19:22 -07002402 pw.println(" isWfcEnabledByPlatform = " + isWfcEnabledByPlatform());
2403 pw.println(" isWfcEnabledByUser = " + isWfcEnabledByUser());
2404 pw.println(" getWfcMode = " + getWfcMode());
2405 pw.println(" isWfcRoamingEnabledByUser = " + isWfcRoamingEnabledByUser());
Jack Yu2f102bd2015-12-28 15:31:48 -08002406
Brad Ebinger479f52c2017-08-28 13:19:22 -07002407 pw.println(" isVtProvisionedOnDevice = " + isVtProvisionedOnDevice());
2408 pw.println(" isWfcProvisionedOnDevice = " + isWfcProvisionedOnDevice());
Jack Yu2f102bd2015-12-28 15:31:48 -08002409 pw.flush();
2410 }
Wink Savilleef36ef62014-06-11 08:39:38 -07002411}