blob: d335fa2ee7e58307e09411244154f53adae5fbf2 [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
19import android.app.PendingIntent;
20import android.content.Context;
21import android.content.Intent;
Pavel Zhamaitsiak4de9cbb2016-02-11 17:21:05 -080022import android.net.Uri;
Wink Savilleef36ef62014-06-11 08:39:38 -070023import android.os.IBinder;
Wink Savilleef36ef62014-06-11 08:39:38 -070024import android.os.Message;
Naveen Kalla525c3a22017-02-06 14:46:42 -080025import android.os.Parcel;
Jonathan Basseri2acea6f2015-07-01 15:00:38 -070026import android.os.PersistableBundle;
Wink Savilleef36ef62014-06-11 08:39:38 -070027import android.os.RemoteException;
Etan Cohenaf55a402014-09-04 22:34:41 -070028import android.os.SystemProperties;
Etan Cohen82f78122014-12-15 10:10:14 -080029import android.provider.Settings;
30import android.telecom.TelecomManager;
Junda Liue7663c02015-06-23 11:16:26 -070031import android.telephony.CarrierConfigManager;
Wink Savilleef36ef62014-06-11 08:39:38 -070032import android.telephony.Rlog;
Meng Wangbb98b9b2016-12-07 16:27:15 -080033import android.telephony.ServiceState;
Etan Cohen82f78122014-12-15 10:10:14 -080034import android.telephony.SubscriptionManager;
Etan Cohencfc784d2014-08-07 18:40:31 -070035import android.telephony.TelephonyManager;
Hall Liue511a202017-08-17 15:49:58 -070036import android.util.Log;
Wink Savilleef36ef62014-06-11 08:39:38 -070037
38import com.android.ims.internal.IImsCallSession;
Naveen Kalla525c3a22017-02-06 14:46:42 -080039import com.android.ims.internal.IImsConfig;
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -070040import com.android.ims.internal.IImsEcbm;
Tyler Gunn4d128b62016-04-13 15:44:38 -070041import com.android.ims.internal.IImsMultiEndpoint;
Brad Ebinger44fd8af2017-12-14 14:24:02 -080042import com.android.ims.internal.IImsRegistrationCallback;
Wink Savilleef36ef62014-06-11 08:39:38 -070043import com.android.ims.internal.IImsRegistrationListener;
Mohamed Abdalkader4d68a982018-01-10 13:29:26 -080044import com.android.ims.internal.IImsServiceController;
45import com.android.ims.internal.IImsSmsListener;
Wink Savilleef36ef62014-06-11 08:39:38 -070046import com.android.ims.internal.IImsUt;
47import com.android.ims.internal.ImsCallSession;
Brad Ebinger16780ff2017-01-26 11:18:21 -080048import com.android.internal.annotations.VisibleForTesting;
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -050049
Jack Yu2f102bd2015-12-28 15:31:48 -080050import java.io.FileDescriptor;
51import java.io.PrintWriter;
Naveen Kalla525c3a22017-02-06 14:46:42 -080052import java.util.ArrayList;
Etan Cohend7727462014-07-12 14:54:10 -070053import java.util.HashMap;
Brad Ebinger16780ff2017-01-26 11:18:21 -080054import java.util.HashSet;
Brad Ebinger16780ff2017-01-26 11:18:21 -080055import java.util.Set;
Malcolm Chen18837ff2017-10-25 17:05:41 -070056import java.util.concurrent.ConcurrentLinkedDeque;
Brad Ebinger44fd8af2017-12-14 14:24:02 -080057import java.util.concurrent.CopyOnWriteArraySet;
Etan Cohend7727462014-07-12 14:54:10 -070058
Wink Savilleef36ef62014-06-11 08:39:38 -070059/**
60 * Provides APIs for IMS services, such as initiating IMS calls, and provides access to
61 * the operator's IMS network. This class is the starting point for any IMS actions.
62 * You can acquire an instance of it with {@link #getInstance getInstance()}.</p>
63 * <p>The APIs in this class allows you to:</p>
64 *
65 * @hide
66 */
67public class ImsManager {
Etan Cohen19604c02014-08-11 14:32:57 -070068
Etan Cohenaf55a402014-09-04 22:34:41 -070069 /*
70 * Debug flag to override configuration flag
71 */
Etan Cohenb651fa52014-10-22 10:51:29 -070072 public static final String PROPERTY_DBG_VOLTE_AVAIL_OVERRIDE = "persist.dbg.volte_avail_ovr";
73 public static final int PROPERTY_DBG_VOLTE_AVAIL_OVERRIDE_DEFAULT = 0;
Etan Cohenea2b5832014-10-23 18:50:35 -070074 public static final String PROPERTY_DBG_VT_AVAIL_OVERRIDE = "persist.dbg.vt_avail_ovr";
75 public static final int PROPERTY_DBG_VT_AVAIL_OVERRIDE_DEFAULT = 0;
Etan Cohena00c9192014-12-23 15:02:29 -080076 public static final String PROPERTY_DBG_WFC_AVAIL_OVERRIDE = "persist.dbg.wfc_avail_ovr";
77 public static final int PROPERTY_DBG_WFC_AVAIL_OVERRIDE_DEFAULT = 0;
Meng Wang9352c432016-06-08 14:22:20 -070078 public static final String PROPERTY_DBG_ALLOW_IMS_OFF_OVERRIDE = "persist.dbg.allow_ims_off";
79 public static final int PROPERTY_DBG_ALLOW_IMS_OFF_OVERRIDE_DEFAULT = 0;
Etan Cohenaf55a402014-09-04 22:34:41 -070080
Wink Savilleef36ef62014-06-11 08:39:38 -070081 /**
Wink Savilleef36ef62014-06-11 08:39:38 -070082 * The result code to be sent back with the incoming call {@link PendingIntent}.
83 * @see #open(PendingIntent, ImsConnectionStateListener)
84 */
85 public static final int INCOMING_CALL_RESULT_CODE = 101;
86
87 /**
88 * Key to retrieve the call ID from an incoming call intent.
89 * @see #open(PendingIntent, ImsConnectionStateListener)
90 */
91 public static final String EXTRA_CALL_ID = "android:imsCallID";
92
93 /**
94 * Action to broadcast when ImsService is up.
95 * Internal use only.
Brad Ebinger16780ff2017-01-26 11:18:21 -080096 * @deprecated
Wink Savilleef36ef62014-06-11 08:39:38 -070097 * @hide
98 */
99 public static final String ACTION_IMS_SERVICE_UP =
100 "com.android.ims.IMS_SERVICE_UP";
101
102 /**
103 * Action to broadcast when ImsService is down.
104 * Internal use only.
Brad Ebinger16780ff2017-01-26 11:18:21 -0800105 * @deprecated
Wink Savilleef36ef62014-06-11 08:39:38 -0700106 * @hide
107 */
108 public static final String ACTION_IMS_SERVICE_DOWN =
109 "com.android.ims.IMS_SERVICE_DOWN";
110
111 /**
Pavel Zhamaitsiak0c2f15c2015-03-12 15:37:54 -0700112 * Action to broadcast when ImsService registration fails.
113 * Internal use only.
114 * @hide
115 */
116 public static final String ACTION_IMS_REGISTRATION_ERROR =
117 "com.android.ims.REGISTRATION_ERROR";
118
119 /**
Etan Cohend7727462014-07-12 14:54:10 -0700120 * Part of the ACTION_IMS_SERVICE_UP or _DOWN intents.
Etan Cohenabbd7882014-09-26 22:35:35 -0700121 * A long value; the phone ID corresponding to the IMS service coming up or down.
Etan Cohend7727462014-07-12 14:54:10 -0700122 * Internal use only.
123 * @hide
124 */
Etan Cohenabbd7882014-09-26 22:35:35 -0700125 public static final String EXTRA_PHONE_ID = "android:phone_id";
Etan Cohend7727462014-07-12 14:54:10 -0700126
127 /**
Wink Savilleef36ef62014-06-11 08:39:38 -0700128 * Action for the incoming call intent for the Phone app.
129 * Internal use only.
130 * @hide
131 */
132 public static final String ACTION_IMS_INCOMING_CALL =
133 "com.android.ims.IMS_INCOMING_CALL";
134
135 /**
136 * Part of the ACTION_IMS_INCOMING_CALL intents.
137 * An integer value; service identifier obtained from {@link ImsManager#open}.
138 * Internal use only.
139 * @hide
140 */
141 public static final String EXTRA_SERVICE_ID = "android:imsServiceId";
142
143 /**
144 * Part of the ACTION_IMS_INCOMING_CALL intents.
145 * An boolean value; Flag to indicate that the incoming call is a normal call or call for USSD.
146 * The value "true" indicates that the incoming call is for USSD.
147 * Internal use only.
148 * @hide
149 */
150 public static final String EXTRA_USSD = "android:ussd";
151
Shriram Ganeshd3adfad2015-05-31 10:06:15 -0700152 /**
153 * Part of the ACTION_IMS_INCOMING_CALL intents.
154 * A boolean value; Flag to indicate whether the call is an unknown
155 * dialing call. Such calls are originated by sending commands (like
156 * AT commands) directly to modem without Android involvement.
157 * Even though they are not incoming calls, they are propagated
158 * to Phone app using same ACTION_IMS_INCOMING_CALL intent.
159 * Internal use only.
160 * @hide
161 */
Anju Mathapati9c033792015-06-16 16:33:16 -0700162 public static final String EXTRA_IS_UNKNOWN_CALL = "android:isUnknown";
Shriram Ganeshd3adfad2015-05-31 10:06:15 -0700163
Malcolm Chen18837ff2017-10-25 17:05:41 -0700164 private static final int SYSTEM_PROPERTY_NOT_SET = -1;
165
166 // -1 indicates a subscriptionProperty value that is never set.
167 private static final int SUB_PROPERTY_NOT_INITIALIZED = -1;
168
Wink Savilleef36ef62014-06-11 08:39:38 -0700169 private static final String TAG = "ImsManager";
170 private static final boolean DBG = true;
171
Wink Saville1e5a38a2014-10-23 10:24:46 -0700172 private static HashMap<Integer, ImsManager> sImsManagerInstances =
173 new HashMap<Integer, ImsManager>();
Etan Cohend7727462014-07-12 14:54:10 -0700174
Wink Savilleef36ef62014-06-11 08:39:38 -0700175 private Context mContext;
Brad Ebinger16417b42017-03-07 13:48:50 -0800176 private CarrierConfigManager mConfigManager;
Etan Cohenabbd7882014-09-26 22:35:35 -0700177 private int mPhoneId;
Brad Ebinger16780ff2017-01-26 11:18:21 -0800178 private final boolean mConfigDynamicBind;
Brad Ebingera7c32432017-11-06 15:19:27 -0800179 private ImsServiceProxy mImsServiceProxy = null;
Wink Savilleef36ef62014-06-11 08:39:38 -0700180 private ImsServiceDeathRecipient mDeathRecipient = new ImsServiceDeathRecipient();
181 // Ut interface for the supplementary service configuration
182 private ImsUt mUt = null;
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -0500183 // Interface to get/set ims config items
184 private ImsConfig mConfig = null;
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -0700185 private boolean mConfigUpdated = false;
Wink Savilleef36ef62014-06-11 08:39:38 -0700186
Pavel Zhamaitsiakf4b90322016-01-26 14:34:09 -0800187 private ImsConfigListener mImsConfigListener;
188
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -0700189 // ECBM interface
190 private ImsEcbm mEcbm = null;
191
Tyler Gunn4d128b62016-04-13 15:44:38 -0700192 private ImsMultiEndpoint mMultiEndpoint = null;
193
Brad Ebinger44fd8af2017-12-14 14:24:02 -0800194 private Set<ImsServiceProxy.IFeatureUpdate> mStatusCallbacks = new CopyOnWriteArraySet<>();
Brad Ebinger16780ff2017-01-26 11:18:21 -0800195
196 // Keep track of the ImsRegistrationListenerProxys that have been created so that we can
197 // remove them from the ImsService.
Brad Ebinger9a0280c2017-06-01 15:58:48 -0700198 private final Set<ImsConnectionStateListener> mRegistrationListeners = new HashSet<>();
199
Brad Ebinger44fd8af2017-12-14 14:24:02 -0800200
201 // Used for compatibility with the old Registration method
202 // TODO: Remove once the compat layer is in place
203 private final ImsRegistrationListenerProxy mImsRegistrationListenerProxy =
Brad Ebinger9a0280c2017-06-01 15:58:48 -0700204 new ImsRegistrationListenerProxy();
Brad Ebinger44fd8af2017-12-14 14:24:02 -0800205 // New API for registration to the ImsService.
206 private final ImsRegistrationCallback mRegistrationCallback = new ImsRegistrationCallback();
207
Brad Ebinger9a0280c2017-06-01 15:58:48 -0700208
209 // When true, we have registered the mRegistrationListenerProxy with the ImsService. Don't do
210 // it again.
211 private boolean mHasRegisteredForProxy = false;
212 private final Object mHasRegisteredLock = new Object();
Brad Ebinger16780ff2017-01-26 11:18:21 -0800213
Amit Mahajan24f7b162016-07-21 16:33:53 -0700214 public static final String TRUE = "true";
215 public static final String FALSE = "false";
Jack Yu643ffe42016-07-08 14:25:46 -0700216
Naveen Kalla525c3a22017-02-06 14:46:42 -0800217 // mRecentDisconnectReasons stores the last 16 disconnect reasons
218 private static final int MAX_RECENT_DISCONNECT_REASONS = 16;
219 private ConcurrentLinkedDeque<ImsReasonInfo> mRecentDisconnectReasons =
220 new ConcurrentLinkedDeque<>();
221
Wink Savilleef36ef62014-06-11 08:39:38 -0700222 /**
223 * Gets a manager instance.
224 *
225 * @param context application context for creating the manager object
Etan Cohenabbd7882014-09-26 22:35:35 -0700226 * @param phoneId the phone ID for the IMS Service
227 * @return the manager instance corresponding to the phoneId
Wink Savilleef36ef62014-06-11 08:39:38 -0700228 */
Etan Cohenabbd7882014-09-26 22:35:35 -0700229 public static ImsManager getInstance(Context context, int phoneId) {
Etan Cohend7727462014-07-12 14:54:10 -0700230 synchronized (sImsManagerInstances) {
Naveen Kalla525c3a22017-02-06 14:46:42 -0800231 if (sImsManagerInstances.containsKey(phoneId)) {
Brad Ebingerff097922017-06-19 15:43:08 -0700232 ImsManager m = sImsManagerInstances.get(phoneId);
233 // May be null for some tests
234 if (m != null) {
235 m.connectIfServiceIsAvailable();
236 }
237 return m;
Naveen Kalla525c3a22017-02-06 14:46:42 -0800238 }
Wink Savilleef36ef62014-06-11 08:39:38 -0700239
Etan Cohenabbd7882014-09-26 22:35:35 -0700240 ImsManager mgr = new ImsManager(context, phoneId);
241 sImsManagerInstances.put(phoneId, mgr);
Etan Cohend7727462014-07-12 14:54:10 -0700242
243 return mgr;
244 }
Wink Savilleef36ef62014-06-11 08:39:38 -0700245 }
246
Etan Cohen45b5f312014-08-19 15:55:08 -0700247 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800248 * Returns the user configuration of Enhanced 4G LTE Mode setting.
249 *
250 * @deprecated Doesn't support MSIM devices. Use
Brad Ebinger479f52c2017-08-28 13:19:22 -0700251 * {@link #isEnhanced4gLteModeSettingEnabledByUser()} instead.
Etan Cohen45b5f312014-08-19 15:55:08 -0700252 */
253 public static boolean isEnhanced4gLteModeSettingEnabledByUser(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700254 ImsManager mgr = ImsManager.getInstance(context,
255 SubscriptionManager.getDefaultVoicePhoneId());
256 if (mgr != null) {
257 return mgr.isEnhanced4gLteModeSettingEnabledByUser();
Sungmin Choi2f1af952016-02-01 17:15:35 +0900258 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700259 loge("isEnhanced4gLteModeSettingEnabledByUser: ImsManager null, returning default value.");
260 return false;
Etan Cohen45b5f312014-08-19 15:55:08 -0700261 }
262
263 /**
manabu, shimoda96aee542017-10-06 15:39:36 +0900264 * Returns the user configuration of Enhanced 4G LTE Mode setting for slot. If the option is
265 * not editable ({@link CarrierConfigManager#KEY_EDITABLE_ENHANCED_4G_LTE_BOOL} is false), or
266 * the setting is not initialized, this method will return default value specified by
267 * {@link CarrierConfigManager#KEY_ENHANCED_4G_LTE_ON_BY_DEFAULT_BOOL}.
268 *
269 * Note that even if the setting was set, it may no longer be editable. If this is the case we
270 * return the default value.
Brad Ebinger16417b42017-03-07 13:48:50 -0800271 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700272 public boolean isEnhanced4gLteModeSettingEnabledByUser() {
Malcolm Chen212ca652017-09-28 17:28:45 -0700273 int setting = SubscriptionManager.getIntegerSubscriptionProperty(
274 getSubId(), SubscriptionManager.ENHANCED_4G_MODE_ENABLED,
275 SUB_PROPERTY_NOT_INITIALIZED, mContext);
manabu, shimoda96aee542017-10-06 15:39:36 +0900276 boolean onByDefault = getBooleanCarrierConfig(
277 CarrierConfigManager.KEY_ENHANCED_4G_LTE_ON_BY_DEFAULT_BOOL);
Malcolm Chen212ca652017-09-28 17:28:45 -0700278
manabu, shimoda96aee542017-10-06 15:39:36 +0900279 // If Enhanced 4G LTE Mode is uneditable or not initialized, we use the default value
280 if (!getBooleanCarrierConfig(CarrierConfigManager.KEY_EDITABLE_ENHANCED_4G_LTE_BOOL)
281 || setting == SUB_PROPERTY_NOT_INITIALIZED) {
282 return onByDefault;
283 } else {
284 return (setting == ImsConfig.FeatureValueConstants.ON);
285 }
Brad Ebinger16417b42017-03-07 13:48:50 -0800286 }
287
288 /**
289 * Change persistent Enhanced 4G LTE Mode setting.
290 *
Brad Ebinger479f52c2017-08-28 13:19:22 -0700291 * @deprecated Doesn't support MSIM devices. Use {@link #setEnhanced4gLteModeSetting(boolean)}
Brad Ebinger16417b42017-03-07 13:48:50 -0800292 * instead.
Etan Cohen82f78122014-12-15 10:10:14 -0800293 */
294 public static void setEnhanced4gLteModeSetting(Context context, boolean enabled) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700295 ImsManager mgr = ImsManager.getInstance(context,
296 SubscriptionManager.getDefaultVoicePhoneId());
297 if (mgr != null) {
298 mgr.setEnhanced4gLteModeSetting(enabled);
Etan Cohen82f78122014-12-15 10:10:14 -0800299 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700300 loge("setEnhanced4gLteModeSetting: ImsManager null, value not set.");
Etan Cohen82f78122014-12-15 10:10:14 -0800301 }
302
303 /**
manabu, shimoda96aee542017-10-06 15:39:36 +0900304 * Change persistent Enhanced 4G LTE Mode setting. If the option is not editable
Brad Ebinger16417b42017-03-07 13:48:50 -0800305 * ({@link CarrierConfigManager#KEY_EDITABLE_ENHANCED_4G_LTE_BOOL} is false), this method will
manabu, shimoda96aee542017-10-06 15:39:36 +0900306 * set the setting to the default value specified by
307 * {@link CarrierConfigManager#KEY_ENHANCED_4G_LTE_ON_BY_DEFAULT_BOOL}.
Brad Ebinger16417b42017-03-07 13:48:50 -0800308 *
309 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700310 public void setEnhanced4gLteModeSetting(boolean enabled) {
manabu, shimoda96aee542017-10-06 15:39:36 +0900311 // If editable=false, we must keep default advanced 4G mode.
312 if (!getBooleanCarrierConfig(CarrierConfigManager.KEY_EDITABLE_ENHANCED_4G_LTE_BOOL)) {
313 enabled = getBooleanCarrierConfig(
314 CarrierConfigManager.KEY_ENHANCED_4G_LTE_ON_BY_DEFAULT_BOOL);
315 }
Brad Ebinger16417b42017-03-07 13:48:50 -0800316
Malcolm Chen212ca652017-09-28 17:28:45 -0700317 int prevSetting = SubscriptionManager.getIntegerSubscriptionProperty(
318 getSubId(), SubscriptionManager.ENHANCED_4G_MODE_ENABLED,
319 SUB_PROPERTY_NOT_INITIALIZED, mContext);
Brad Ebinger16417b42017-03-07 13:48:50 -0800320
manabu, shimoda96aee542017-10-06 15:39:36 +0900321 if (prevSetting != (enabled ?
322 ImsConfig.FeatureValueConstants.ON :
323 ImsConfig.FeatureValueConstants.OFF)) {
Malcolm Chen212ca652017-09-28 17:28:45 -0700324 SubscriptionManager.setSubscriptionProperty(getSubId(),
325 SubscriptionManager.ENHANCED_4G_MODE_ENABLED, booleanToPropertyString(enabled));
326 if (isNonTtyOrTtyOnVolteEnabled()) {
327 try {
328 setAdvanced4GMode(enabled);
329 } catch (ImsException ie) {
330 // do nothing
331 }
Brad Ebinger16417b42017-03-07 13:48:50 -0800332 }
333 }
334 }
335
336 /**
Etan Cohen82f78122014-12-15 10:10:14 -0800337 * Indicates whether the call is non-TTY or if TTY - whether TTY on VoLTE is
338 * supported.
Brad Ebinger16417b42017-03-07 13:48:50 -0800339 * @deprecated Does not support MSIM devices. Please use
Brad Ebinger479f52c2017-08-28 13:19:22 -0700340 * {@link #isNonTtyOrTtyOnVolteEnabled()} instead.
Etan Cohen82f78122014-12-15 10:10:14 -0800341 */
342 public static boolean isNonTtyOrTtyOnVolteEnabled(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700343 ImsManager mgr = ImsManager.getInstance(context,
344 SubscriptionManager.getDefaultVoicePhoneId());
345 if (mgr != null) {
346 return mgr.isNonTtyOrTtyOnVolteEnabled();
347 }
348 loge("isNonTtyOrTtyOnVolteEnabled: ImsManager null, returning default value.");
349 return false;
350 }
351
352 /**
353 * Indicates whether the call is non-TTY or if TTY - whether TTY on VoLTE is
354 * supported on a per slot basis.
355 */
356 public boolean isNonTtyOrTtyOnVolteEnabled() {
357 if (getBooleanCarrierConfig(
fionaxu5803ef02016-03-08 11:48:48 -0800358 CarrierConfigManager.KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL)) {
Etan Cohen82f78122014-12-15 10:10:14 -0800359 return true;
360 }
361
Brad Ebinger479f52c2017-08-28 13:19:22 -0700362 TelecomManager tm = (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
Hall Liue511a202017-08-17 15:49:58 -0700363 if (tm == null) {
364 Log.w(TAG, "isNonTtyOrTtyOnVolteEnabled: telecom not available");
365 return true;
366 }
367 return tm.getCurrentTtyMode() == TelecomManager.TTY_MODE_OFF;
Etan Cohen82f78122014-12-15 10:10:14 -0800368 }
369
370 /**
Etan Cohenea2b5832014-10-23 18:50:35 -0700371 * Returns a platform configuration for VoLTE which may override the user setting.
Brad Ebinger16417b42017-03-07 13:48:50 -0800372 * @deprecated Does not support MSIM devices. Please use
Brad Ebinger479f52c2017-08-28 13:19:22 -0700373 * {@link #isVolteEnabledByPlatform()} instead.
Etan Cohen45b5f312014-08-19 15:55:08 -0700374 */
Etan Cohenea2b5832014-10-23 18:50:35 -0700375 public static boolean isVolteEnabledByPlatform(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700376 ImsManager mgr = ImsManager.getInstance(context,
377 SubscriptionManager.getDefaultVoicePhoneId());
378 if (mgr != null) {
379 return mgr.isVolteEnabledByPlatform();
Etan Cohenaf55a402014-09-04 22:34:41 -0700380 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700381 loge("isVolteEnabledByPlatform: ImsManager null, returning default value.");
382 return false;
Etan Cohenb5388a32014-11-26 11:57:47 -0800383 }
384
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700385 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800386 * Returns a platform configuration for VoLTE which may override the user setting on a per Slot
387 * basis.
388 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700389 public boolean isVolteEnabledByPlatform() {
Malcolm Chen18837ff2017-10-25 17:05:41 -0700390 // We first read the per slot value. If doesn't exist, we read the general value. If still
391 // doesn't exist, we use the hardcoded default value.
392 if (SystemProperties.getInt(
393 PROPERTY_DBG_VOLTE_AVAIL_OVERRIDE + Integer.toString(mPhoneId),
394 SYSTEM_PROPERTY_NOT_SET) == 1 ||
395 SystemProperties.getInt(PROPERTY_DBG_VOLTE_AVAIL_OVERRIDE,
396 SYSTEM_PROPERTY_NOT_SET) == 1) {
Brad Ebinger16417b42017-03-07 13:48:50 -0800397 return true;
398 }
399
400 return mContext.getResources().getBoolean(
401 com.android.internal.R.bool.config_device_volte_available)
Malcolm Chen212ca652017-09-28 17:28:45 -0700402 && getBooleanCarrierConfig(CarrierConfigManager.KEY_CARRIER_VOLTE_AVAILABLE_BOOL)
Brad Ebinger479f52c2017-08-28 13:19:22 -0700403 && isGbaValid();
Brad Ebinger16417b42017-03-07 13:48:50 -0800404 }
405
406 /**
407 * Indicates whether VoLTE is provisioned on device.
408 *
409 * @deprecated Does not support MSIM devices. Please use
Brad Ebinger479f52c2017-08-28 13:19:22 -0700410 * {@link #isVolteProvisionedOnDevice()} instead.
Etan Cohenb5388a32014-11-26 11:57:47 -0800411 */
412 public static boolean isVolteProvisionedOnDevice(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700413 ImsManager mgr = ImsManager.getInstance(context,
414 SubscriptionManager.getDefaultVoicePhoneId());
415 if (mgr != null) {
416 return mgr.isVolteProvisionedOnDevice();
Etan Cohenb5388a32014-11-26 11:57:47 -0800417 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700418 loge("isVolteProvisionedOnDevice: ImsManager null, returning default value.");
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700419 return true;
420 }
421
422 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800423 * Indicates whether VoLTE is provisioned on this slot.
424 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700425 public boolean isVolteProvisionedOnDevice() {
426 if (getBooleanCarrierConfig(
Brad Ebinger16417b42017-03-07 13:48:50 -0800427 CarrierConfigManager.KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL)) {
428 return isVolteProvisioned();
429 }
430
431 return true;
432 }
433
434 /**
Meng Wang54fd41a2017-04-12 11:44:47 -0700435 * Indicates whether VoWifi is provisioned on device.
436 *
437 * When CarrierConfig KEY_CARRIER_VOLTE_OVERRIDE_WFC_PROVISIONING_BOOL is true, and VoLTE is not
438 * provisioned on device, this method returns false.
Brad Ebinger16417b42017-03-07 13:48:50 -0800439 *
440 * @deprecated Does not support MSIM devices. Please use
Brad Ebinger479f52c2017-08-28 13:19:22 -0700441 * {@link #isWfcProvisionedOnDevice()} instead.
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700442 */
443 public static boolean isWfcProvisionedOnDevice(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700444 ImsManager mgr = ImsManager.getInstance(context,
445 SubscriptionManager.getDefaultVoicePhoneId());
446 if (mgr != null) {
447 return mgr.isWfcProvisionedOnDevice();
Meng Wang54fd41a2017-04-12 11:44:47 -0700448 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700449 loge("isWfcProvisionedOnDevice: ImsManager null, returning default value.");
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700450 return true;
451 }
452
453 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800454 * Indicates whether VoWifi is provisioned on slot.
Meng Wang54fd41a2017-04-12 11:44:47 -0700455 *
456 * When CarrierConfig KEY_CARRIER_VOLTE_OVERRIDE_WFC_PROVISIONING_BOOL is true, and VoLTE is not
457 * provisioned on device, this method returns false.
Brad Ebinger16417b42017-03-07 13:48:50 -0800458 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700459 public boolean isWfcProvisionedOnDevice() {
460 if (getBooleanCarrierConfig(
Meng Wang54fd41a2017-04-12 11:44:47 -0700461 CarrierConfigManager.KEY_CARRIER_VOLTE_OVERRIDE_WFC_PROVISIONING_BOOL)) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700462 if (!isVolteProvisionedOnDevice()) {
Meng Wang54fd41a2017-04-12 11:44:47 -0700463 return false;
464 }
465 }
466
Brad Ebinger479f52c2017-08-28 13:19:22 -0700467 if (getBooleanCarrierConfig(
Brad Ebinger16417b42017-03-07 13:48:50 -0800468 CarrierConfigManager.KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL)) {
Meng Wang54fd41a2017-04-12 11:44:47 -0700469 return isWfcProvisioned();
Brad Ebinger16417b42017-03-07 13:48:50 -0800470 }
471
472 return true;
473 }
474
475 /**
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700476 * Indicates whether VT is provisioned on device
Brad Ebinger16417b42017-03-07 13:48:50 -0800477 *
478 * @deprecated Does not support MSIM devices. Please use
Brad Ebinger479f52c2017-08-28 13:19:22 -0700479 * {@link #isVtProvisionedOnDevice()} instead.
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700480 */
481 public static boolean isVtProvisionedOnDevice(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700482 ImsManager mgr = ImsManager.getInstance(context,
483 SubscriptionManager.getDefaultVoicePhoneId());
484 if (mgr != null) {
485 return mgr.isVtProvisionedOnDevice();
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700486 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700487 loge("isVtProvisionedOnDevice: ImsManager null, returning default value.");
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700488 return true;
Etan Cohenb651fa52014-10-22 10:51:29 -0700489 }
490
Etan Cohenea2b5832014-10-23 18:50:35 -0700491 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800492 * Indicates whether VT is provisioned on slot.
493 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700494 public boolean isVtProvisionedOnDevice() {
495 if (getBooleanCarrierConfig(
Brad Ebinger16417b42017-03-07 13:48:50 -0800496 CarrierConfigManager.KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL)) {
497 return isVtProvisioned();
498 }
499
500 return true;
501 }
502
503 /**
Etan Cohenea2b5832014-10-23 18:50:35 -0700504 * Returns a platform configuration for VT which may override the user setting.
505 *
506 * Note: VT presumes that VoLTE is enabled (these are configuration settings
507 * which must be done correctly).
Brad Ebinger16417b42017-03-07 13:48:50 -0800508 *
509 * @deprecated Does not support MSIM devices. Please use
Brad Ebinger479f52c2017-08-28 13:19:22 -0700510 * {@link #isVtEnabledByPlatform()} instead.
Etan Cohenea2b5832014-10-23 18:50:35 -0700511 */
Etan Cohenb651fa52014-10-22 10:51:29 -0700512 public static boolean isVtEnabledByPlatform(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700513 ImsManager mgr = ImsManager.getInstance(context,
514 SubscriptionManager.getDefaultVoicePhoneId());
515 if (mgr != null) {
516 return mgr.isVtEnabledByPlatform();
Etan Cohenea2b5832014-10-23 18:50:35 -0700517 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700518 loge("isVtEnabledByPlatform: ImsManager null, returning default value.");
519 return false;
Etan Cohen45b5f312014-08-19 15:55:08 -0700520 }
521
Etan Cohena00c9192014-12-23 15:02:29 -0800522 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800523 * Returns a platform configuration for VT which may override the user setting.
524 *
525 * Note: VT presumes that VoLTE is enabled (these are configuration settings
526 * which must be done correctly).
527 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700528 public boolean isVtEnabledByPlatform() {
Malcolm Chen18837ff2017-10-25 17:05:41 -0700529 // We first read the per slot value. If doesn't exist, we read the general value. If still
530 // doesn't exist, we use the hardcoded default value.
531 if (SystemProperties.getInt(PROPERTY_DBG_VT_AVAIL_OVERRIDE +
532 Integer.toString(mPhoneId), SYSTEM_PROPERTY_NOT_SET) == 1 ||
533 SystemProperties.getInt(
534 PROPERTY_DBG_VT_AVAIL_OVERRIDE, SYSTEM_PROPERTY_NOT_SET) == 1) {
Brad Ebinger16417b42017-03-07 13:48:50 -0800535 return true;
536 }
537
538 return mContext.getResources().getBoolean(
539 com.android.internal.R.bool.config_device_vt_available) &&
Malcolm Chen212ca652017-09-28 17:28:45 -0700540 getBooleanCarrierConfig(CarrierConfigManager.KEY_CARRIER_VT_AVAILABLE_BOOL) &&
Brad Ebinger479f52c2017-08-28 13:19:22 -0700541 isGbaValid();
Brad Ebinger16417b42017-03-07 13:48:50 -0800542 }
543
544 /**
Etan Cohena7d32e82015-05-04 18:02:09 -0700545 * Returns the user configuration of VT setting
Brad Ebinger16417b42017-03-07 13:48:50 -0800546 * @deprecated Does not support MSIM devices. Please use
Brad Ebinger479f52c2017-08-28 13:19:22 -0700547 * {@link #isVtEnabledByUser()} instead.
Etan Cohena7d32e82015-05-04 18:02:09 -0700548 */
549 public static boolean isVtEnabledByUser(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700550 ImsManager mgr = ImsManager.getInstance(context,
551 SubscriptionManager.getDefaultVoicePhoneId());
552 if (mgr != null) {
553 return mgr.isVtEnabledByUser();
554 }
555 loge("isVtEnabledByUser: ImsManager null, returning default value.");
556 return false;
Etan Cohena7d32e82015-05-04 18:02:09 -0700557 }
558
559 /**
Malcolm Chen212ca652017-09-28 17:28:45 -0700560 * Returns the user configuration of VT setting per slot. If not set, it
561 * returns true as default value.
Brad Ebinger16417b42017-03-07 13:48:50 -0800562 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700563 public boolean isVtEnabledByUser() {
Malcolm Chen212ca652017-09-28 17:28:45 -0700564 int setting = SubscriptionManager.getIntegerSubscriptionProperty(
565 getSubId(), SubscriptionManager.VT_IMS_ENABLED,
566 SUB_PROPERTY_NOT_INITIALIZED, mContext);
567
568 // If it's never set, by default we return true.
manabu, shimoda96aee542017-10-06 15:39:36 +0900569 return (setting == SUB_PROPERTY_NOT_INITIALIZED
570 || setting == ImsConfig.FeatureValueConstants.ON);
Brad Ebinger16417b42017-03-07 13:48:50 -0800571 }
572
573 /**
Etan Cohena7d32e82015-05-04 18:02:09 -0700574 * Change persistent VT enabled setting
Brad Ebinger16417b42017-03-07 13:48:50 -0800575 *
Brad Ebinger479f52c2017-08-28 13:19:22 -0700576 * @deprecated Does not support MSIM devices. Please use {@link #setVtSetting(boolean)} instead.
Etan Cohena7d32e82015-05-04 18:02:09 -0700577 */
578 public static void setVtSetting(Context context, boolean enabled) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700579 ImsManager mgr = ImsManager.getInstance(context,
Etan Cohena7d32e82015-05-04 18:02:09 -0700580 SubscriptionManager.getDefaultVoicePhoneId());
Brad Ebinger479f52c2017-08-28 13:19:22 -0700581 if (mgr != null) {
582 mgr.setVtSetting(enabled);
Etan Cohena7d32e82015-05-04 18:02:09 -0700583 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700584 loge("setVtSetting: ImsManager null, can not set value.");
Etan Cohena7d32e82015-05-04 18:02:09 -0700585 }
586
Brad Ebinger16417b42017-03-07 13:48:50 -0800587 /**
588 * Change persistent VT enabled setting for slot.
589 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700590 public void setVtSetting(boolean enabled) {
Malcolm Chen212ca652017-09-28 17:28:45 -0700591 SubscriptionManager.setSubscriptionProperty(getSubId(),
592 SubscriptionManager.VT_IMS_ENABLED,
593 booleanToPropertyString(enabled));
Brad Ebinger16417b42017-03-07 13:48:50 -0800594 try {
595 ImsConfig config = getConfigInterface();
596 config.setFeatureValue(ImsConfig.FeatureConstants.FEATURE_TYPE_VIDEO_OVER_LTE,
597 TelephonyManager.NETWORK_TYPE_LTE,
598 enabled ? ImsConfig.FeatureValueConstants.ON
599 : ImsConfig.FeatureValueConstants.OFF,
600 mImsConfigListener);
601
602 if (enabled) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700603 log("setVtSetting(b) : turnOnIms");
Brad Ebinger16417b42017-03-07 13:48:50 -0800604 turnOnIms();
Brad Ebinger479f52c2017-08-28 13:19:22 -0700605 } else if (isVolteEnabledByPlatform()
606 && (!isVolteEnabledByPlatform()
607 || !isEnhanced4gLteModeSettingEnabledByUser())) {
608 log("setVtSetting(b) : imsServiceAllowTurnOff -> turnOffIms");
Brad Ebinger16417b42017-03-07 13:48:50 -0800609 turnOffIms();
610 }
611 } catch (ImsException e) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700612 loge("setVtSetting(b): ", e);
Brad Ebinger16417b42017-03-07 13:48:50 -0800613 }
614 }
615
616 /**
Meng Wang9352c432016-06-08 14:22:20 -0700617 * Returns whether turning off ims is allowed by platform.
618 * The platform property may override the carrier config.
Brad Ebinger16417b42017-03-07 13:48:50 -0800619 *
620 * @deprecated Does not support MSIM devices. Please use
Brad Ebinger479f52c2017-08-28 13:19:22 -0700621 * {@link #isTurnOffImsAllowedByPlatform()} instead.
Meng Wang9352c432016-06-08 14:22:20 -0700622 */
623 private static boolean isTurnOffImsAllowedByPlatform(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700624 ImsManager mgr = ImsManager.getInstance(context,
625 SubscriptionManager.getDefaultVoicePhoneId());
626 if (mgr != null) {
627 return mgr.isTurnOffImsAllowedByPlatform();
Meng Wang9352c432016-06-08 14:22:20 -0700628 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700629 loge("isTurnOffImsAllowedByPlatform: ImsManager null, returning default value.");
630 return true;
Meng Wang9352c432016-06-08 14:22:20 -0700631 }
632
Etan Cohena7d32e82015-05-04 18:02:09 -0700633 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800634 * Returns whether turning off ims is allowed by platform.
635 * The platform property may override the carrier config.
636 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700637 private boolean isTurnOffImsAllowedByPlatform() {
Malcolm Chen18837ff2017-10-25 17:05:41 -0700638 // We first read the per slot value. If doesn't exist, we read the general value. If still
639 // doesn't exist, we use the hardcoded default value.
640 if (SystemProperties.getInt(PROPERTY_DBG_ALLOW_IMS_OFF_OVERRIDE +
641 Integer.toString(mPhoneId), SYSTEM_PROPERTY_NOT_SET) == 1 ||
642 SystemProperties.getInt(
643 PROPERTY_DBG_ALLOW_IMS_OFF_OVERRIDE, SYSTEM_PROPERTY_NOT_SET) == 1) {
Brad Ebinger16417b42017-03-07 13:48:50 -0800644 return true;
645 }
Malcolm Chen18837ff2017-10-25 17:05:41 -0700646
Brad Ebinger479f52c2017-08-28 13:19:22 -0700647 return getBooleanCarrierConfig(
Brad Ebinger16417b42017-03-07 13:48:50 -0800648 CarrierConfigManager.KEY_CARRIER_ALLOW_TURNOFF_IMS_BOOL);
649 }
650
651 /**
Etan Cohena00c9192014-12-23 15:02:29 -0800652 * Returns the user configuration of WFC setting
Brad Ebinger16417b42017-03-07 13:48:50 -0800653 *
654 * @deprecated Does not support MSIM devices. Please use
Brad Ebinger479f52c2017-08-28 13:19:22 -0700655 * {@link #isWfcEnabledByUser()} instead.
Etan Cohena00c9192014-12-23 15:02:29 -0800656 */
657 public static boolean isWfcEnabledByUser(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700658 ImsManager mgr = ImsManager.getInstance(context,
659 SubscriptionManager.getDefaultVoicePhoneId());
660 if (mgr != null) {
661 return mgr.isWfcEnabledByUser();
662 }
663 loge("isWfcEnabledByUser: ImsManager null, returning default value.");
664 return true;
Etan Cohena00c9192014-12-23 15:02:29 -0800665 }
666
667 /**
Malcolm Chen212ca652017-09-28 17:28:45 -0700668 * Returns the user configuration of WFC setting for slot. If not set, it
669 * queries CarrierConfig value as default.
Brad Ebinger16417b42017-03-07 13:48:50 -0800670 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700671 public boolean isWfcEnabledByUser() {
Malcolm Chen212ca652017-09-28 17:28:45 -0700672 int setting = SubscriptionManager.getIntegerSubscriptionProperty(
673 getSubId(), SubscriptionManager.WFC_IMS_ENABLED,
674 SUB_PROPERTY_NOT_INITIALIZED, mContext);
675
676 // SUB_PROPERTY_NOT_INITIALIZED indicates it's never set in sub db.
677 if (setting == SUB_PROPERTY_NOT_INITIALIZED) {
678 return getBooleanCarrierConfig(
679 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ENABLED_BOOL);
680 } else {
manabu, shimoda96aee542017-10-06 15:39:36 +0900681 return setting == ImsConfig.FeatureValueConstants.ON;
Malcolm Chen212ca652017-09-28 17:28:45 -0700682 }
Brad Ebinger16417b42017-03-07 13:48:50 -0800683 }
684
685 /**
686 * Change persistent WFC enabled setting.
687 * @deprecated Does not support MSIM devices. Please use
Brad Ebinger479f52c2017-08-28 13:19:22 -0700688 * {@link #setWfcSetting} instead.
Etan Cohena00c9192014-12-23 15:02:29 -0800689 */
690 public static void setWfcSetting(Context context, boolean enabled) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700691 ImsManager mgr = ImsManager.getInstance(context,
Etan Cohena00c9192014-12-23 15:02:29 -0800692 SubscriptionManager.getDefaultVoicePhoneId());
Brad Ebinger479f52c2017-08-28 13:19:22 -0700693 if (mgr != null) {
694 mgr.setWfcSetting(enabled);
Etan Cohena00c9192014-12-23 15:02:29 -0800695 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700696 loge("setWfcSetting: ImsManager null, can not set value.");
Etan Cohena00c9192014-12-23 15:02:29 -0800697 }
698
699 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800700 * Change persistent WFC enabled setting for slot.
701 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700702 public void setWfcSetting(boolean enabled) {
Malcolm Chen212ca652017-09-28 17:28:45 -0700703 SubscriptionManager.setSubscriptionProperty(getSubId(),
704 SubscriptionManager.WFC_IMS_ENABLED, booleanToPropertyString(enabled));
Brad Ebinger16417b42017-03-07 13:48:50 -0800705
Brad Ebinger479f52c2017-08-28 13:19:22 -0700706 setWfcNonPersistent(enabled, getWfcMode());
Meng Wang51c09072017-03-27 10:47:45 -0700707 }
708
709 /**
710 * Non-persistently change WFC enabled setting and WFC mode for slot
711 *
712 * @param wfcMode The WFC preference if WFC is enabled
713 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700714 public void setWfcNonPersistent(boolean enabled, int wfcMode) {
Meng Wang51c09072017-03-27 10:47:45 -0700715 int imsFeatureValue =
716 enabled ? ImsConfig.FeatureValueConstants.ON : ImsConfig.FeatureValueConstants.OFF;
717 // Force IMS to register over LTE when turning off WFC
718 int imsWfcModeFeatureValue =
719 enabled ? wfcMode : ImsConfig.WfcModeFeatureValueConstants.CELLULAR_PREFERRED;
720
Brad Ebinger16417b42017-03-07 13:48:50 -0800721 try {
722 ImsConfig config = getConfigInterface();
723 config.setFeatureValue(ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_WIFI,
724 TelephonyManager.NETWORK_TYPE_IWLAN,
Meng Wang51c09072017-03-27 10:47:45 -0700725 imsFeatureValue,
Brad Ebinger16417b42017-03-07 13:48:50 -0800726 mImsConfigListener);
727
728 if (enabled) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700729 log("setWfcSetting() : turnOnIms");
Brad Ebinger16417b42017-03-07 13:48:50 -0800730 turnOnIms();
Brad Ebinger479f52c2017-08-28 13:19:22 -0700731 } else if (isTurnOffImsAllowedByPlatform()
732 && (!isVolteEnabledByPlatform()
733 || !isEnhanced4gLteModeSettingEnabledByUser())) {
734 log("setWfcSetting() : imsServiceAllowTurnOff -> turnOffIms");
Brad Ebinger16417b42017-03-07 13:48:50 -0800735 turnOffIms();
736 }
737
Brad Ebinger479f52c2017-08-28 13:19:22 -0700738 setWfcModeInternal(imsWfcModeFeatureValue);
Brad Ebinger16417b42017-03-07 13:48:50 -0800739 } catch (ImsException e) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700740 loge("setWfcSetting(): ", e);
Brad Ebinger16417b42017-03-07 13:48:50 -0800741 }
742 }
743
744 /**
745 * Returns the user configuration of WFC preference setting.
746 *
Malcolm Chen212ca652017-09-28 17:28:45 -0700747 * @deprecated Doesn't support MSIM devices. Use {@link #getWfcMode(boolean roaming)} instead.
Etan Cohena00c9192014-12-23 15:02:29 -0800748 */
749 public static int getWfcMode(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700750 ImsManager mgr = ImsManager.getInstance(context,
751 SubscriptionManager.getDefaultVoicePhoneId());
752 if (mgr != null) {
753 return mgr.getWfcMode();
754 }
755 loge("getWfcMode: ImsManager null, returning default value.");
756 return ImsConfig.WfcModeFeatureValueConstants.WIFI_ONLY;
Etan Cohena00c9192014-12-23 15:02:29 -0800757 }
758
759 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800760 * Returns the user configuration of WFC preference setting
Malcolm Chen212ca652017-09-28 17:28:45 -0700761 * @deprecated. Use {@link #getWfcMode(boolean roaming)} instead.
Brad Ebinger16417b42017-03-07 13:48:50 -0800762 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700763 public int getWfcMode() {
Malcolm Chen212ca652017-09-28 17:28:45 -0700764 return getWfcMode(false);
Brad Ebinger16417b42017-03-07 13:48:50 -0800765 }
766
767 /**
768 * Change persistent WFC preference setting.
769 *
Brad Ebinger479f52c2017-08-28 13:19:22 -0700770 * @deprecated Doesn't support MSIM devices. Use {@link #setWfcMode(int)} instead.
Etan Cohena00c9192014-12-23 15:02:29 -0800771 */
772 public static void setWfcMode(Context context, int wfcMode) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700773 ImsManager mgr = ImsManager.getInstance(context,
774 SubscriptionManager.getDefaultVoicePhoneId());
775 if (mgr != null) {
776 mgr.setWfcMode(wfcMode);
777 }
778 loge("setWfcMode: ImsManager null, can not set value.");
Pavel Zhamaitsiak9e6eca22015-03-16 15:30:53 -0700779 }
780
Meng Wang37477012016-09-20 09:59:56 -0700781 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800782 * Change persistent WFC preference setting for slot.
783 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700784 public void setWfcMode(int wfcMode) {
785 if (DBG) log("setWfcMode(i) - setting=" + wfcMode);
Malcolm Chen212ca652017-09-28 17:28:45 -0700786
787 SubscriptionManager.setSubscriptionProperty(getSubId(),
788 SubscriptionManager.WFC_IMS_MODE, Integer.toString(wfcMode));
Brad Ebinger16417b42017-03-07 13:48:50 -0800789
Brad Ebinger479f52c2017-08-28 13:19:22 -0700790 setWfcModeInternal(wfcMode);
Brad Ebinger16417b42017-03-07 13:48:50 -0800791 }
792
793 /**
Suresh Koleti76491082017-04-21 18:39:50 +0530794 * Changes the WFC mode to its default value for Carriers with non-editable WFC settings.
795 */
796 private void updateDefaultWfcMode() {
797 if (DBG) log("updateDefaultWfcMode");
Brad Ebinger479f52c2017-08-28 13:19:22 -0700798 if (!getBooleanCarrierConfig(CarrierConfigManager.KEY_EDITABLE_WFC_MODE_BOOL)) {
799 setWfcMode(getIntCarrierConfig(
Suresh Koleti76491082017-04-21 18:39:50 +0530800 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_MODE_INT));
801 }
802 }
803
804 /**
Meng Wang37477012016-09-20 09:59:56 -0700805 * Returns the user configuration of WFC preference setting
806 *
807 * @param roaming {@code false} for home network setting, {@code true} for roaming setting
Brad Ebinger16417b42017-03-07 13:48:50 -0800808 *
Brad Ebinger479f52c2017-08-28 13:19:22 -0700809 * @deprecated Doesn't support MSIM devices. Use {@link #getWfcMode(boolean)} instead.
Meng Wang37477012016-09-20 09:59:56 -0700810 */
811 public static int getWfcMode(Context context, boolean roaming) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700812 ImsManager mgr = ImsManager.getInstance(context,
813 SubscriptionManager.getDefaultVoicePhoneId());
814 if (mgr != null) {
815 return mgr.getWfcMode(roaming);
Meng Wang37477012016-09-20 09:59:56 -0700816 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700817 loge("getWfcMode: ImsManager null, returning default value.");
818 return ImsConfig.WfcModeFeatureValueConstants.WIFI_ONLY;
Meng Wang37477012016-09-20 09:59:56 -0700819 }
820
821 /**
Malcolm Chen212ca652017-09-28 17:28:45 -0700822 * Returns the user configuration of WFC preference setting for slot. If not set, it
823 * queries CarrierConfig value as default.
Brad Ebinger16417b42017-03-07 13:48:50 -0800824 *
825 * @param roaming {@code false} for home network setting, {@code true} for roaming setting
826 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700827 public int getWfcMode(boolean roaming) {
Brad Ebinger16417b42017-03-07 13:48:50 -0800828 int setting = 0;
829 if (!roaming) {
Malcolm Chen212ca652017-09-28 17:28:45 -0700830 setting = SubscriptionManager.getIntegerSubscriptionProperty(
831 getSubId(), SubscriptionManager.WFC_IMS_MODE,
832 SUB_PROPERTY_NOT_INITIALIZED, mContext);
833
834 // SUB_PROPERTY_NOT_INITIALIZED indicates it's never set in sub db.
835 if (setting == SUB_PROPERTY_NOT_INITIALIZED) {
836 setting = getIntCarrierConfig(
837 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_MODE_INT);
838 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700839 if (DBG) log("getWfcMode - setting=" + setting);
Brad Ebinger16417b42017-03-07 13:48:50 -0800840 } else {
Malcolm Chen212ca652017-09-28 17:28:45 -0700841 setting = SubscriptionManager.getIntegerSubscriptionProperty(
842 getSubId(), SubscriptionManager.WFC_IMS_ROAMING_MODE,
843 SUB_PROPERTY_NOT_INITIALIZED, mContext);
844
845 // SUB_PROPERTY_NOT_INITIALIZED indicates it's never set in sub db.
846 if (setting == SUB_PROPERTY_NOT_INITIALIZED) {
847 setting = getIntCarrierConfig(
848 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_MODE_INT);
849 }
850
Brad Ebinger479f52c2017-08-28 13:19:22 -0700851 if (DBG) log("getWfcMode (roaming) - setting=" + setting);
Brad Ebinger16417b42017-03-07 13:48:50 -0800852 }
853 return setting;
854 }
855
856 /**
Meng Wang37477012016-09-20 09:59:56 -0700857 * Change persistent WFC preference setting
858 *
859 * @param roaming {@code false} for home network setting, {@code true} for roaming setting
Brad Ebinger16417b42017-03-07 13:48:50 -0800860 *
Brad Ebinger479f52c2017-08-28 13:19:22 -0700861 * @deprecated Doesn't support MSIM devices. Please use {@link #setWfcMode(int, boolean)}
862 * instead.
Meng Wang37477012016-09-20 09:59:56 -0700863 */
864 public static void setWfcMode(Context context, int wfcMode, boolean roaming) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700865 ImsManager mgr = ImsManager.getInstance(context,
866 SubscriptionManager.getDefaultVoicePhoneId());
867 if (mgr != null) {
868 mgr.setWfcMode(wfcMode, roaming);
Meng Wang37477012016-09-20 09:59:56 -0700869 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700870 loge("setWfcMode: ImsManager null, can not set value.");
Meng Wang37477012016-09-20 09:59:56 -0700871 }
872
Brad Ebinger16417b42017-03-07 13:48:50 -0800873 /**
874 * Change persistent WFC preference setting
875 *
876 * @param roaming {@code false} for home network setting, {@code true} for roaming setting
877 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700878 public void setWfcMode(int wfcMode, boolean roaming) {
Brad Ebinger16417b42017-03-07 13:48:50 -0800879 if (!roaming) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700880 if (DBG) log("setWfcMode(i,b) - setting=" + wfcMode);
Malcolm Chen212ca652017-09-28 17:28:45 -0700881 SubscriptionManager.setSubscriptionProperty(getSubId(),
882 SubscriptionManager.WFC_IMS_MODE, Integer.toString(wfcMode));
Brad Ebinger16417b42017-03-07 13:48:50 -0800883 } else {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700884 if (DBG) log("setWfcMode(i,b) (roaming) - setting=" + wfcMode);
Malcolm Chen212ca652017-09-28 17:28:45 -0700885 SubscriptionManager.setSubscriptionProperty(getSubId(),
886 SubscriptionManager.WFC_IMS_ROAMING_MODE, Integer.toString(wfcMode));
Brad Ebinger16417b42017-03-07 13:48:50 -0800887 }
888
Brad Ebinger479f52c2017-08-28 13:19:22 -0700889 TelephonyManager tm = (TelephonyManager)
890 mContext.getSystemService(Context.TELEPHONY_SERVICE);
891 if (roaming == tm.isNetworkRoaming(getSubId())) {
892 setWfcModeInternal(wfcMode);
893 }
894 }
895
896 private int getSubId() {
Brad Ebinger16417b42017-03-07 13:48:50 -0800897 int[] subIds = SubscriptionManager.getSubId(mPhoneId);
898 int subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
899 if (subIds != null && subIds.length >= 1) {
900 subId = subIds[0];
901 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700902 return subId;
Brad Ebinger16417b42017-03-07 13:48:50 -0800903 }
904
Pavel Zhamaitsiak9e6eca22015-03-16 15:30:53 -0700905 private static void setWfcModeInternal(Context context, int wfcMode) {
Etan Cohena00c9192014-12-23 15:02:29 -0800906 final ImsManager imsManager = ImsManager.getInstance(context,
907 SubscriptionManager.getDefaultVoicePhoneId());
908 if (imsManager != null) {
909 final int value = wfcMode;
Pavel Zhamaitsiak47aeacf2016-03-30 18:54:55 -0700910 Thread thread = new Thread(new Runnable() {
Etan Cohena00c9192014-12-23 15:02:29 -0800911 public void run() {
912 try {
913 imsManager.getConfigInterface().setProvisionedValue(
914 ImsConfig.ConfigConstants.VOICE_OVER_WIFI_MODE,
915 value);
916 } catch (ImsException e) {
917 // do nothing
918 }
919 }
920 });
Pavel Zhamaitsiak47aeacf2016-03-30 18:54:55 -0700921 thread.start();
Etan Cohena00c9192014-12-23 15:02:29 -0800922 }
923 }
924
Brad Ebinger479f52c2017-08-28 13:19:22 -0700925 private void setWfcModeInternal(int wfcMode) {
Brad Ebinger16417b42017-03-07 13:48:50 -0800926 final int value = wfcMode;
927 Thread thread = new Thread(() -> {
Malcolm Chen212ca652017-09-28 17:28:45 -0700928 try {
929 getConfigInterface().setProvisionedValue(
930 ImsConfig.ConfigConstants.VOICE_OVER_WIFI_MODE, value);
931 } catch (ImsException e) {
932 // do nothing
933 }
Brad Ebinger16417b42017-03-07 13:48:50 -0800934 });
935 thread.start();
936 }
937
Etan Cohena00c9192014-12-23 15:02:29 -0800938 /**
939 * Returns the user configuration of WFC roaming setting
Brad Ebinger16417b42017-03-07 13:48:50 -0800940 *
941 * @deprecated Does not support MSIM devices. Please use
Brad Ebinger479f52c2017-08-28 13:19:22 -0700942 * {@link #isWfcRoamingEnabledByUser()} instead.
Etan Cohena00c9192014-12-23 15:02:29 -0800943 */
944 public static boolean isWfcRoamingEnabledByUser(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700945 ImsManager mgr = ImsManager.getInstance(context,
946 SubscriptionManager.getDefaultVoicePhoneId());
947 if (mgr != null) {
948 return mgr.isWfcRoamingEnabledByUser();
949 }
950 loge("isWfcRoamingEnabledByUser: ImsManager null, returning default value.");
951 return false;
Etan Cohena00c9192014-12-23 15:02:29 -0800952 }
953
954 /**
Malcolm Chen212ca652017-09-28 17:28:45 -0700955 * Returns the user configuration of WFC roaming setting for slot. If not set, it
956 * queries CarrierConfig value as default.
Brad Ebinger16417b42017-03-07 13:48:50 -0800957 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700958 public boolean isWfcRoamingEnabledByUser() {
Malcolm Chen212ca652017-09-28 17:28:45 -0700959 int setting = SubscriptionManager.getIntegerSubscriptionProperty(
960 getSubId(), SubscriptionManager.WFC_IMS_ROAMING_ENABLED,
961 SUB_PROPERTY_NOT_INITIALIZED, mContext);
962 if (setting == SUB_PROPERTY_NOT_INITIALIZED) {
963 return getBooleanCarrierConfig(
964 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_ENABLED_BOOL);
965 } else {
manabu, shimoda96aee542017-10-06 15:39:36 +0900966 return setting == ImsConfig.FeatureValueConstants.ON;
Malcolm Chen212ca652017-09-28 17:28:45 -0700967 }
Brad Ebinger16417b42017-03-07 13:48:50 -0800968 }
969
970 /**
Etan Cohena00c9192014-12-23 15:02:29 -0800971 * Change persistent WFC roaming enabled setting
972 */
973 public static void setWfcRoamingSetting(Context context, boolean enabled) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700974 ImsManager mgr = ImsManager.getInstance(context,
Etan Cohena00c9192014-12-23 15:02:29 -0800975 SubscriptionManager.getDefaultVoicePhoneId());
Brad Ebinger479f52c2017-08-28 13:19:22 -0700976 if (mgr != null) {
977 mgr.setWfcRoamingSetting(enabled);
Etan Cohena00c9192014-12-23 15:02:29 -0800978 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700979 loge("setWfcRoamingSetting: ImsManager null, value not set.");
Etan Cohena00c9192014-12-23 15:02:29 -0800980 }
981
982 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800983 * Change persistent WFC roaming enabled setting
984 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700985 public void setWfcRoamingSetting(boolean enabled) {
Malcolm Chen212ca652017-09-28 17:28:45 -0700986 SubscriptionManager.setSubscriptionProperty(getSubId(),
987 SubscriptionManager.WFC_IMS_ROAMING_ENABLED, booleanToPropertyString(enabled)
988 );
Brad Ebinger16417b42017-03-07 13:48:50 -0800989
990 setWfcRoamingSettingInternal(enabled);
991 }
992
993 private void setWfcRoamingSettingInternal(boolean enabled) {
994 final int value = enabled
995 ? ImsConfig.FeatureValueConstants.ON
996 : ImsConfig.FeatureValueConstants.OFF;
997 Thread thread = new Thread(() -> {
Malcolm Chen212ca652017-09-28 17:28:45 -0700998 try {
999 getConfigInterface().setProvisionedValue(
1000 ImsConfig.ConfigConstants.VOICE_OVER_WIFI_ROAMING, value);
1001 } catch (ImsException e) {
1002 // do nothing
1003 }
Brad Ebinger16417b42017-03-07 13:48:50 -08001004 });
1005 thread.start();
1006 }
1007
1008 /**
Etan Cohena00c9192014-12-23 15:02:29 -08001009 * Returns a platform configuration for WFC which may override the user
1010 * setting. Note: WFC presumes that VoLTE is enabled (these are
1011 * configuration settings which must be done correctly).
Brad Ebinger16417b42017-03-07 13:48:50 -08001012 *
Brad Ebinger479f52c2017-08-28 13:19:22 -07001013 * @deprecated Doesn't work for MSIM devices. Use {@link #isWfcEnabledByPlatform()}
Brad Ebinger16417b42017-03-07 13:48:50 -08001014 * instead.
Etan Cohena00c9192014-12-23 15:02:29 -08001015 */
1016 public static boolean isWfcEnabledByPlatform(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -07001017 ImsManager mgr = ImsManager.getInstance(context,
1018 SubscriptionManager.getDefaultVoicePhoneId());
1019 if (mgr != null) {
1020 return mgr.isWfcEnabledByPlatform();
Etan Cohena00c9192014-12-23 15:02:29 -08001021 }
Brad Ebinger479f52c2017-08-28 13:19:22 -07001022 loge("isWfcEnabledByPlatform: ImsManager null, returning default value.");
1023 return false;
Pavel Zhamaitsiak57911d12015-10-20 14:26:34 -07001024 }
1025
1026 /**
Brad Ebinger16417b42017-03-07 13:48:50 -08001027 * Returns a platform configuration for WFC which may override the user
1028 * setting per slot. Note: WFC presumes that VoLTE is enabled (these are
1029 * configuration settings which must be done correctly).
1030 */
Brad Ebinger479f52c2017-08-28 13:19:22 -07001031 public boolean isWfcEnabledByPlatform() {
Malcolm Chen18837ff2017-10-25 17:05:41 -07001032 // We first read the per slot value. If doesn't exist, we read the general value. If still
1033 // doesn't exist, we use the hardcoded default value.
1034 if (SystemProperties.getInt(PROPERTY_DBG_WFC_AVAIL_OVERRIDE +
1035 Integer.toString(mPhoneId), SYSTEM_PROPERTY_NOT_SET) == 1 ||
1036 SystemProperties.getInt(
1037 PROPERTY_DBG_WFC_AVAIL_OVERRIDE, SYSTEM_PROPERTY_NOT_SET) == 1) {
Brad Ebinger16417b42017-03-07 13:48:50 -08001038 return true;
1039 }
1040
1041 return mContext.getResources().getBoolean(
1042 com.android.internal.R.bool.config_device_wfc_ims_available) &&
Brad Ebinger479f52c2017-08-28 13:19:22 -07001043 getBooleanCarrierConfig(
Brad Ebinger16417b42017-03-07 13:48:50 -08001044 CarrierConfigManager.KEY_CARRIER_WFC_IMS_AVAILABLE_BOOL) &&
Brad Ebinger479f52c2017-08-28 13:19:22 -07001045 isGbaValid();
Etan Cohena00c9192014-12-23 15:02:29 -08001046 }
1047
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001048 /**
Brad Ebinger16417b42017-03-07 13:48:50 -08001049 * If carrier requires that IMS is only available if GBA capable SIM is used,
1050 * then this function checks GBA bit in EF IST.
1051 *
1052 * Format of EF IST is defined in 3GPP TS 31.103 (Section 4.2.7).
1053 */
Brad Ebinger479f52c2017-08-28 13:19:22 -07001054 private boolean isGbaValid() {
1055 if (getBooleanCarrierConfig(
Brad Ebinger16417b42017-03-07 13:48:50 -08001056 CarrierConfigManager.KEY_CARRIER_IMS_GBA_REQUIRED_BOOL)) {
Brad Ebinger479f52c2017-08-28 13:19:22 -07001057 final TelephonyManager telephonyManager = new TelephonyManager(mContext, getSubId());
Brad Ebinger16417b42017-03-07 13:48:50 -08001058 String efIst = telephonyManager.getIsimIst();
1059 if (efIst == null) {
Brad Ebinger479f52c2017-08-28 13:19:22 -07001060 loge("isGbaValid - ISF is NULL");
Brad Ebinger16417b42017-03-07 13:48:50 -08001061 return true;
1062 }
1063 boolean result = efIst != null && efIst.length() > 1 &&
1064 (0x02 & (byte)efIst.charAt(1)) != 0;
Brad Ebinger479f52c2017-08-28 13:19:22 -07001065 if (DBG) log("isGbaValid - GBA capable=" + result + ", ISF=" + efIst);
Brad Ebinger16417b42017-03-07 13:48:50 -08001066 return result;
1067 }
1068 return true;
1069 }
1070
1071 /**
Malcolm Chen18837ff2017-10-25 17:05:41 -07001072 * Will return with config value or throw an ImsException if we receive an error from
1073 * ImsConfig for that value.
1074 */
1075 private boolean getProvisionedBool(ImsConfig config, int item) throws ImsException {
1076 int value = config.getProvisionedValue(item);
1077 if (value == ImsConfig.OperationStatusConstants.UNKNOWN) {
1078 throw new ImsException("getProvisionedBool failed with error for item: " + item,
1079 ImsReasonInfo.CODE_LOCAL_INTERNAL_ERROR);
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -07001080 }
Malcolm Chen18837ff2017-10-25 17:05:41 -07001081 return config.getProvisionedValue(item) == ImsConfig.FeatureValueConstants.ON;
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -07001082 }
1083
1084 /**
Malcolm Chen18837ff2017-10-25 17:05:41 -07001085 * Will return with config value or return false if we receive an error from
1086 * ImsConfig for that value.
Brad Ebingerbe6cb672017-08-25 14:55:00 -07001087 */
Malcolm Chen18837ff2017-10-25 17:05:41 -07001088 private boolean getProvisionedBoolNoException(int item) {
1089 try {
1090 ImsConfig config = getConfigInterface();
1091 return getProvisionedBool(config, item);
1092 } catch (ImsException ex) {
1093 return false;
Brad Ebingerbe6cb672017-08-25 14:55:00 -07001094 }
1095 }
1096
1097 /**
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001098 * Sync carrier config and user settings with ImsConfig.
1099 *
1100 * @param context for the manager object
1101 * @param phoneId phone id
1102 * @param force update
Brad Ebinger16417b42017-03-07 13:48:50 -08001103 *
Brad Ebinger479f52c2017-08-28 13:19:22 -07001104 * @deprecated Doesn't support MSIM devices. Use {@link #updateImsServiceConfig(boolean)}
1105 * instead.
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001106 */
1107 public static void updateImsServiceConfig(Context context, int phoneId, boolean force) {
Brad Ebinger479f52c2017-08-28 13:19:22 -07001108 ImsManager mgr = ImsManager.getInstance(context, phoneId);
1109 if (mgr != null) {
1110 mgr.updateImsServiceConfig(force);
Pavel Zhamaitsiakfc202992016-03-29 18:07:38 -07001111 }
Brad Ebinger479f52c2017-08-28 13:19:22 -07001112 loge("updateImsServiceConfig: ImsManager null, returning without update.");
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001113 }
1114
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -07001115 /**
Brad Ebinger16417b42017-03-07 13:48:50 -08001116 * Sync carrier config and user settings with ImsConfig.
1117 *
Brad Ebinger16417b42017-03-07 13:48:50 -08001118 * @param force update
1119 */
Brad Ebinger479f52c2017-08-28 13:19:22 -07001120 public void updateImsServiceConfig(boolean force) {
Brad Ebinger16417b42017-03-07 13:48:50 -08001121 if (!force) {
Brad Ebinger479f52c2017-08-28 13:19:22 -07001122 TelephonyManager tm = new TelephonyManager(mContext, getSubId());
1123 if (tm.getSimState() != TelephonyManager.SIM_STATE_READY) {
1124 log("updateImsServiceConfig: SIM not ready");
Brad Ebinger16417b42017-03-07 13:48:50 -08001125 // Don't disable IMS if SIM is not ready
1126 return;
1127 }
1128 }
1129
1130 if (!mConfigUpdated || force) {
1131 try {
Brad Ebinger16417b42017-03-07 13:48:50 -08001132 // TODO: Extend ImsConfig API and set all feature values in single function call.
1133
1134 // Note: currently the order of updates is set to produce different order of
1135 // setFeatureValue() function calls from setAdvanced4GMode(). This is done to
1136 // differentiate this code path from vendor code perspective.
1137 boolean isImsUsed = updateVolteFeatureValue();
1138 isImsUsed |= updateWfcFeatureAndProvisionedValues();
1139 isImsUsed |= updateVideoCallFeatureValue();
1140
Brad Ebinger479f52c2017-08-28 13:19:22 -07001141 if (isImsUsed || !isTurnOffImsAllowedByPlatform()) {
Brad Ebinger16417b42017-03-07 13:48:50 -08001142 // Turn on IMS if it is used.
1143 // Also, if turning off is not allowed for current carrier,
1144 // we need to turn IMS on because it might be turned off before
1145 // phone switched to current carrier.
Brad Ebinger479f52c2017-08-28 13:19:22 -07001146 log("updateImsServiceConfig: turnOnIms");
Brad Ebinger16417b42017-03-07 13:48:50 -08001147 turnOnIms();
1148 } else {
1149 // Turn off IMS if it is not used AND turning off is allowed for carrier.
Brad Ebinger479f52c2017-08-28 13:19:22 -07001150 log("updateImsServiceConfig: turnOffIms");
Brad Ebinger16417b42017-03-07 13:48:50 -08001151 turnOffIms();
1152 }
1153
1154 mConfigUpdated = true;
1155 } catch (ImsException e) {
Brad Ebinger479f52c2017-08-28 13:19:22 -07001156 loge("updateImsServiceConfig: ", e);
Brad Ebinger16417b42017-03-07 13:48:50 -08001157 mConfigUpdated = false;
1158 }
1159 }
1160 }
1161
1162 /**
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -07001163 * Update VoLTE config
1164 * @return whether feature is On
1165 * @throws ImsException
1166 */
1167 private boolean updateVolteFeatureValue() throws ImsException {
Brad Ebinger479f52c2017-08-28 13:19:22 -07001168 boolean available = isVolteEnabledByPlatform();
1169 boolean enabled = isEnhanced4gLteModeSettingEnabledByUser();
1170 boolean isNonTty = isNonTtyOrTtyOnVolteEnabled();
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -08001171 boolean isFeatureOn = available && enabled && isNonTty;
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001172
1173 log("updateVolteFeatureValue: available = " + available
1174 + ", enabled = " + enabled
1175 + ", nonTTY = " + isNonTty);
1176
1177 getConfigInterface().setFeatureValue(
1178 ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_LTE,
1179 TelephonyManager.NETWORK_TYPE_LTE,
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -08001180 isFeatureOn ?
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001181 ImsConfig.FeatureValueConstants.ON :
1182 ImsConfig.FeatureValueConstants.OFF,
Pavel Zhamaitsiakf4b90322016-01-26 14:34:09 -08001183 mImsConfigListener);
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -07001184
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -08001185 return isFeatureOn;
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001186 }
1187
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -07001188 /**
Jack Yu643ffe42016-07-08 14:25:46 -07001189 * Update video call over LTE config
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -07001190 * @return whether feature is On
1191 * @throws ImsException
1192 */
1193 private boolean updateVideoCallFeatureValue() throws ImsException {
Brad Ebinger479f52c2017-08-28 13:19:22 -07001194 boolean available = isVtEnabledByPlatform();
1195 boolean enabled = isVtEnabledByUser();
1196 boolean isNonTty = isNonTtyOrTtyOnVolteEnabled();
Amit Mahajan24f7b162016-07-21 16:33:53 -07001197 boolean isDataEnabled = isDataEnabled();
Brad Ebinger479f52c2017-08-28 13:19:22 -07001198 boolean ignoreDataEnabledChanged = getBooleanCarrierConfig(
Jack Yu57781852016-11-16 17:20:38 -08001199 CarrierConfigManager.KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS);
Jack Yu643ffe42016-07-08 14:25:46 -07001200
Jack Yu57781852016-11-16 17:20:38 -08001201 boolean isFeatureOn = available && enabled && isNonTty
1202 && (ignoreDataEnabledChanged || isDataEnabled);
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001203
1204 log("updateVideoCallFeatureValue: available = " + available
1205 + ", enabled = " + enabled
Jack Yu643ffe42016-07-08 14:25:46 -07001206 + ", nonTTY = " + isNonTty
Amit Mahajan24f7b162016-07-21 16:33:53 -07001207 + ", data enabled = " + isDataEnabled);
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001208
1209 getConfigInterface().setFeatureValue(
1210 ImsConfig.FeatureConstants.FEATURE_TYPE_VIDEO_OVER_LTE,
1211 TelephonyManager.NETWORK_TYPE_LTE,
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -08001212 isFeatureOn ?
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001213 ImsConfig.FeatureValueConstants.ON :
1214 ImsConfig.FeatureValueConstants.OFF,
Pavel Zhamaitsiakf4b90322016-01-26 14:34:09 -08001215 mImsConfigListener);
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -07001216
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -08001217 return isFeatureOn;
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001218 }
1219
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -07001220 /**
1221 * Update WFC config
1222 * @return whether feature is On
1223 * @throws ImsException
1224 */
1225 private boolean updateWfcFeatureAndProvisionedValues() throws ImsException {
Brad Ebinger479f52c2017-08-28 13:19:22 -07001226 TelephonyManager tm = new TelephonyManager(mContext, getSubId());
1227 boolean isNetworkRoaming = tm.isNetworkRoaming();
1228 boolean available = isWfcEnabledByPlatform();
1229 boolean enabled = isWfcEnabledByUser();
Suresh Koleti76491082017-04-21 18:39:50 +05301230 updateDefaultWfcMode();
Brad Ebinger479f52c2017-08-28 13:19:22 -07001231 int mode = getWfcMode(isNetworkRoaming);
1232 boolean roaming = isWfcRoamingEnabledByUser();
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -08001233 boolean isFeatureOn = available && enabled;
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001234
1235 log("updateWfcFeatureAndProvisionedValues: available = " + available
1236 + ", enabled = " + enabled
1237 + ", mode = " + mode
1238 + ", roaming = " + roaming);
1239
1240 getConfigInterface().setFeatureValue(
Pavel Zhamaitsiake6f99432015-09-11 10:29:30 -07001241 ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_WIFI,
1242 TelephonyManager.NETWORK_TYPE_IWLAN,
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -08001243 isFeatureOn ?
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001244 ImsConfig.FeatureValueConstants.ON :
1245 ImsConfig.FeatureValueConstants.OFF,
Pavel Zhamaitsiakf4b90322016-01-26 14:34:09 -08001246 mImsConfigListener);
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001247
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -08001248 if (!isFeatureOn) {
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001249 mode = ImsConfig.WfcModeFeatureValueConstants.CELLULAR_PREFERRED;
1250 roaming = false;
1251 }
1252 setWfcModeInternal(mContext, mode);
Brad Ebinger16417b42017-03-07 13:48:50 -08001253 setWfcRoamingSettingInternal(roaming);
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -07001254
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -08001255 return isFeatureOn;
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001256 }
1257
Brad Ebinger16780ff2017-01-26 11:18:21 -08001258 /**
Brad Ebinger479f52c2017-08-28 13:19:22 -07001259 * Do NOT use this directly, instead use {@link #getInstance(Context, int)}.
Brad Ebinger16780ff2017-01-26 11:18:21 -08001260 */
1261 @VisibleForTesting
1262 public ImsManager(Context context, int phoneId) {
Wink Savilleef36ef62014-06-11 08:39:38 -07001263 mContext = context;
Etan Cohenabbd7882014-09-26 22:35:35 -07001264 mPhoneId = phoneId;
Brad Ebinger16780ff2017-01-26 11:18:21 -08001265 mConfigDynamicBind = mContext.getResources().getBoolean(
1266 com.android.internal.R.bool.config_dynamic_bind_ims);
Brad Ebinger16417b42017-03-07 13:48:50 -08001267 mConfigManager = (CarrierConfigManager) context.getSystemService(
1268 Context.CARRIER_CONFIG_SERVICE);
Brad Ebinger16780ff2017-01-26 11:18:21 -08001269 createImsService();
1270 }
1271
1272 /**
Brad Ebinger16780ff2017-01-26 11:18:21 -08001273 * @return Whether or not ImsManager is configured to Dynamically bind or not to support legacy
1274 * devices.
1275 */
1276 public boolean isDynamicBinding() {
1277 return mConfigDynamicBind;
Wink Savilleef36ef62014-06-11 08:39:38 -07001278 }
1279
Etan Cohenf4311122015-02-26 17:47:13 -08001280 /*
Brad Ebingerff097922017-06-19 15:43:08 -07001281 * Returns a flag indicating whether the IMS service is available. If it is not available,
1282 * it will try to connect before reporting failure.
Etan Cohenf4311122015-02-26 17:47:13 -08001283 */
1284 public boolean isServiceAvailable() {
Brad Ebingerff097922017-06-19 15:43:08 -07001285 connectIfServiceIsAvailable();
Brad Ebinger16780ff2017-01-26 11:18:21 -08001286 // mImsServiceProxy will always create an ImsServiceProxy.
1287 return mImsServiceProxy.isBinderAlive();
Etan Cohenf4311122015-02-26 17:47:13 -08001288 }
1289
Suresh Koleticc3139c2017-11-03 18:23:57 +05301290 /*
1291 * Returns a flag indicating whether the IMS service is ready to send requests to lower layers.
1292 */
1293 public boolean isServiceReady() {
1294 connectIfServiceIsAvailable();
1295 return mImsServiceProxy.isBinderReady();
1296 }
1297
Brad Ebingerff097922017-06-19 15:43:08 -07001298 /**
1299 * If the service is available, try to reconnect.
1300 */
1301 public void connectIfServiceIsAvailable() {
1302 if (mImsServiceProxy == null || !mImsServiceProxy.isBinderAlive()) {
1303 createImsService();
1304 }
1305 }
1306
Pavel Zhamaitsiakf4b90322016-01-26 14:34:09 -08001307 public void setImsConfigListener(ImsConfigListener listener) {
1308 mImsConfigListener = listener;
1309 }
1310
Brad Ebingerb10b61e2017-04-18 11:45:26 -07001311
1312 /**
1313 * Adds a callback for status changed events if the binder is already available. If it is not,
1314 * this method will throw an ImsException.
1315 */
Brad Ebinger44fd8af2017-12-14 14:24:02 -08001316 public void addNotifyStatusChangedCallbackIfAvailable(ImsServiceProxy.IFeatureUpdate c)
Brad Ebingerb10b61e2017-04-18 11:45:26 -07001317 throws ImsException {
1318 if (!mImsServiceProxy.isBinderAlive()) {
1319 throw new ImsException("Binder is not active!",
1320 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1321 }
Brad Ebinger16780ff2017-01-26 11:18:21 -08001322 if (c != null) {
1323 mStatusCallbacks.add(c);
1324 }
1325 }
1326
Brad Ebinger44fd8af2017-12-14 14:24:02 -08001327 public void removeNotifyStatusChangedCallback(ImsServiceProxy.IFeatureUpdate c) {
1328 if (c != null) {
1329 mStatusCallbacks.remove(c);
1330 } else {
1331 Log.w(TAG, "removeNotifyStatusChangedCallback: callback is null!");
1332 }
1333 }
1334
Wink Savilleef36ef62014-06-11 08:39:38 -07001335 /**
1336 * Opens the IMS service for making calls and/or receiving generic IMS calls.
1337 * The caller may make subsquent calls through {@link #makeCall}.
1338 * The IMS service will register the device to the operator's network with the credentials
1339 * (from ISIM) periodically in order to receive calls from the operator's network.
1340 * When the IMS service receives a new call, it will send out an intent with
1341 * the provided action string.
1342 * The intent contains a call ID extra {@link getCallId} and it can be used to take a call.
1343 *
1344 * @param serviceClass a service class specified in {@link ImsServiceClass}
1345 * For VoLTE service, it MUST be a {@link ImsServiceClass#MMTEL}.
1346 * @param incomingCallPendingIntent When an incoming call is received,
1347 * the IMS service will call {@link PendingIntent#send(Context, int, Intent)} to
1348 * send back the intent to the caller with {@link #INCOMING_CALL_RESULT_CODE}
1349 * as the result code and the intent to fill in the call ID; It cannot be null
1350 * @param listener To listen to IMS registration events; It cannot be null
1351 * @return identifier (greater than 0) for the specified service
1352 * @throws NullPointerException if {@code incomingCallPendingIntent}
1353 * or {@code listener} is null
1354 * @throws ImsException if calling the IMS service results in an error
1355 * @see #getCallId
Brad Ebinger16780ff2017-01-26 11:18:21 -08001356 * @see #getImsSessionId
Wink Savilleef36ef62014-06-11 08:39:38 -07001357 */
1358 public int open(int serviceClass, PendingIntent incomingCallPendingIntent,
1359 ImsConnectionStateListener listener) throws ImsException {
1360 checkAndThrowExceptionIfServiceUnavailable();
1361
1362 if (incomingCallPendingIntent == null) {
1363 throw new NullPointerException("incomingCallPendingIntent can't be null");
1364 }
1365
1366 if (listener == null) {
1367 throw new NullPointerException("listener can't be null");
1368 }
1369
1370 int result = 0;
1371
1372 try {
Brad Ebinger57b11892017-06-13 16:21:35 -07001373 // Register a stub implementation of the ImsRegistrationListener. There is the
1374 // possibility that if we use the real implementation of the ImsRegistrationListener,
1375 // it will be added twice.
1376 // TODO: Remove ImsRegistrationListener from startSession API (b/62588776)
Brad Ebinger16780ff2017-01-26 11:18:21 -08001377 result = mImsServiceProxy.startSession(incomingCallPendingIntent,
Brad Ebinger57b11892017-06-13 16:21:35 -07001378 new ImsRegistrationListenerBase());
1379 addRegistrationListener(listener);
1380 log("open: Session started and registration listener added.");
Wink Savilleef36ef62014-06-11 08:39:38 -07001381 } catch (RemoteException e) {
1382 throw new ImsException("open()", e,
1383 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1384 }
1385
1386 if (result <= 0) {
1387 // If the return value is a minus value,
1388 // it means that an error occurred in the service.
1389 // So, it needs to convert to the reason code specified in ImsReasonInfo.
1390 throw new ImsException("open()", (result * (-1)));
1391 }
1392
1393 return result;
1394 }
1395
1396 /**
Pavel Zhamaitsiakce410172016-04-15 10:55:56 -07001397 * Adds registration listener to the IMS service.
1398 *
1399 * @param serviceClass a service class specified in {@link ImsServiceClass}
1400 * For VoLTE service, it MUST be a {@link ImsServiceClass#MMTEL}.
1401 * @param listener To listen to IMS registration events; It cannot be null
1402 * @throws NullPointerException if {@code listener} is null
1403 * @throws ImsException if calling the IMS service results in an error
Brad Ebinger9a0280c2017-06-01 15:58:48 -07001404 *
1405 * @deprecated Use {@link #addRegistrationListener(ImsConnectionStateListener)} instead.
Pavel Zhamaitsiakce410172016-04-15 10:55:56 -07001406 */
1407 public void addRegistrationListener(int serviceClass, ImsConnectionStateListener listener)
1408 throws ImsException {
Brad Ebinger9a0280c2017-06-01 15:58:48 -07001409 addRegistrationListener(listener);
1410 }
1411
1412 /**
1413 * Adds registration listener to the IMS service.
1414 *
1415 * @param listener To listen to IMS registration events; It cannot be null
1416 * @throws NullPointerException if {@code listener} is null
1417 * @throws ImsException if calling the IMS service results in an error
1418 */
Brad Ebinger44fd8af2017-12-14 14:24:02 -08001419 public void addRegistrationListener(ImsConnectionStateListener listener) throws ImsException {
Pavel Zhamaitsiakce410172016-04-15 10:55:56 -07001420 if (listener == null) {
1421 throw new NullPointerException("listener can't be null");
1422 }
Brad Ebinger57b11892017-06-13 16:21:35 -07001423 // We only want this Proxy registered once.
Brad Ebinger9a0280c2017-06-01 15:58:48 -07001424 synchronized (mHasRegisteredLock) {
1425 if (!mHasRegisteredForProxy) {
1426 try {
Brad Ebinger57b11892017-06-13 16:21:35 -07001427 checkAndThrowExceptionIfServiceUnavailable();
Brad Ebinger44fd8af2017-12-14 14:24:02 -08001428 // TODO: Remove once new MmTelFeature is merged in
1429 mImsServiceProxy.addRegistrationListener(mImsRegistrationListenerProxy);
1430 mImsServiceProxy.getRegistration().addRegistrationCallback(
1431 mRegistrationCallback);
1432 log("Registration Callback/Listener registered.");
Brad Ebinger9a0280c2017-06-01 15:58:48 -07001433 // Only record if there isn't a RemoteException.
1434 mHasRegisteredForProxy = true;
1435 } catch (RemoteException e) {
1436 throw new ImsException("addRegistrationListener()", e,
1437 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1438 }
1439 }
1440 }
1441 synchronized (mRegistrationListeners) {
Brad Ebinger57b11892017-06-13 16:21:35 -07001442 log("Local registration listener added: " + listener);
Brad Ebinger9a0280c2017-06-01 15:58:48 -07001443 mRegistrationListeners.add(listener);
Pavel Zhamaitsiakce410172016-04-15 10:55:56 -07001444 }
1445 }
1446
1447 /**
Brad Ebinger16780ff2017-01-26 11:18:21 -08001448 * Removes the registration listener from the IMS service.
1449 *
Brad Ebinger16780ff2017-01-26 11:18:21 -08001450 * @param listener Previously registered listener that will be removed. Can not be null.
1451 * @throws NullPointerException if {@code listener} is null
1452 * @throws ImsException if calling the IMS service results in an error
1453 * instead.
1454 */
Brad Ebingerb5f30c72017-02-17 14:54:31 -08001455 public void removeRegistrationListener(ImsConnectionStateListener listener)
Brad Ebinger16780ff2017-01-26 11:18:21 -08001456 throws ImsException {
Brad Ebinger16780ff2017-01-26 11:18:21 -08001457 if (listener == null) {
1458 throw new NullPointerException("listener can't be null");
1459 }
1460
Brad Ebinger9a0280c2017-06-01 15:58:48 -07001461 synchronized (mRegistrationListeners) {
Brad Ebinger57b11892017-06-13 16:21:35 -07001462 log("Local registration listener removed: " + listener);
Brad Ebinger9a0280c2017-06-01 15:58:48 -07001463 mRegistrationListeners.remove(listener);
Brad Ebinger16780ff2017-01-26 11:18:21 -08001464 }
1465 }
1466
1467 /**
Wink Savilleef36ef62014-06-11 08:39:38 -07001468 * Closes the specified service ({@link ImsServiceClass}) not to make/receive calls.
1469 * All the resources that were allocated to the service are also released.
1470 *
Brad Ebinger16780ff2017-01-26 11:18:21 -08001471 * @param sessionId a session id to be closed which is obtained from {@link ImsManager#open}
Wink Savilleef36ef62014-06-11 08:39:38 -07001472 * @throws ImsException if calling the IMS service results in an error
1473 */
Brad Ebinger16780ff2017-01-26 11:18:21 -08001474 public void close(int sessionId) throws ImsException {
Wink Savilleef36ef62014-06-11 08:39:38 -07001475 checkAndThrowExceptionIfServiceUnavailable();
1476
1477 try {
Brad Ebinger16780ff2017-01-26 11:18:21 -08001478 mImsServiceProxy.endSession(sessionId);
Wink Savilleef36ef62014-06-11 08:39:38 -07001479 } catch (RemoteException e) {
1480 throw new ImsException("close()", e,
1481 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1482 } finally {
1483 mUt = null;
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -05001484 mConfig = null;
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -07001485 mEcbm = null;
Tyler Gunn4d128b62016-04-13 15:44:38 -07001486 mMultiEndpoint = null;
Wink Savilleef36ef62014-06-11 08:39:38 -07001487 }
1488 }
1489
1490 /**
1491 * Gets the configuration interface to provision / withdraw the supplementary service settings.
1492 *
Wink Savilleef36ef62014-06-11 08:39:38 -07001493 * @return the Ut interface instance
1494 * @throws ImsException if getting the Ut interface results in an error
1495 */
Brad Ebingerb5f30c72017-02-17 14:54:31 -08001496 public ImsUtInterface getSupplementaryServiceConfiguration()
Wink Savilleef36ef62014-06-11 08:39:38 -07001497 throws ImsException {
Brad Ebinger16780ff2017-01-26 11:18:21 -08001498 // FIXME: manage the multiple Ut interfaces based on the session id
Brad Ebinger138b4a62017-06-20 16:29:50 -07001499 if (mUt != null && mUt.isBinderAlive()) {
1500 return mUt;
Wink Savilleef36ef62014-06-11 08:39:38 -07001501 }
1502
Brad Ebinger138b4a62017-06-20 16:29:50 -07001503 checkAndThrowExceptionIfServiceUnavailable();
1504 try {
1505 IImsUt iUt = mImsServiceProxy.getUtInterface();
1506
1507 if (iUt == null) {
1508 throw new ImsException("getSupplementaryServiceConfiguration()",
1509 ImsReasonInfo.CODE_UT_NOT_SUPPORTED);
1510 }
1511
1512 mUt = new ImsUt(iUt);
1513 } catch (RemoteException e) {
1514 throw new ImsException("getSupplementaryServiceConfiguration()", e,
1515 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1516 }
Wink Savilleef36ef62014-06-11 08:39:38 -07001517 return mUt;
1518 }
1519
1520 /**
1521 * Checks if the IMS service has successfully registered to the IMS network
1522 * with the specified service & call type.
1523 *
Wink Savilleef36ef62014-06-11 08:39:38 -07001524 * @param serviceType a service type that is specified in {@link ImsCallProfile}
1525 * {@link ImsCallProfile#SERVICE_TYPE_NORMAL}
1526 * {@link ImsCallProfile#SERVICE_TYPE_EMERGENCY}
1527 * @param callType a call type that is specified in {@link ImsCallProfile}
1528 * {@link ImsCallProfile#CALL_TYPE_VOICE_N_VIDEO}
1529 * {@link ImsCallProfile#CALL_TYPE_VOICE}
1530 * {@link ImsCallProfile#CALL_TYPE_VT}
1531 * {@link ImsCallProfile#CALL_TYPE_VS}
1532 * @return true if the specified service id is connected to the IMS network;
1533 * false otherwise
1534 * @throws ImsException if calling the IMS service results in an error
1535 */
Brad Ebingerb5f30c72017-02-17 14:54:31 -08001536 public boolean isConnected(int serviceType, int callType)
Wink Savilleef36ef62014-06-11 08:39:38 -07001537 throws ImsException {
1538 checkAndThrowExceptionIfServiceUnavailable();
1539
1540 try {
Brad Ebingerb5f30c72017-02-17 14:54:31 -08001541 return mImsServiceProxy.isConnected(serviceType, callType);
Wink Savilleef36ef62014-06-11 08:39:38 -07001542 } catch (RemoteException e) {
1543 throw new ImsException("isServiceConnected()", e,
1544 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1545 }
1546 }
1547
1548 /**
1549 * Checks if the specified IMS service is opend.
1550 *
Wink Savilleef36ef62014-06-11 08:39:38 -07001551 * @return true if the specified service id is opened; false otherwise
1552 * @throws ImsException if calling the IMS service results in an error
1553 */
Brad Ebingerb5f30c72017-02-17 14:54:31 -08001554 public boolean isOpened() throws ImsException {
Wink Savilleef36ef62014-06-11 08:39:38 -07001555 checkAndThrowExceptionIfServiceUnavailable();
1556
1557 try {
Brad Ebingerb5f30c72017-02-17 14:54:31 -08001558 return mImsServiceProxy.isOpened();
Wink Savilleef36ef62014-06-11 08:39:38 -07001559 } catch (RemoteException e) {
1560 throw new ImsException("isOpened()", e,
1561 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1562 }
1563 }
1564
1565 /**
1566 * Creates a {@link ImsCallProfile} from the service capabilities & IMS registration state.
1567 *
Brad Ebinger16780ff2017-01-26 11:18:21 -08001568 * @param sessionId a session id which is obtained from {@link ImsManager#open}
Wink Savilleef36ef62014-06-11 08:39:38 -07001569 * @param serviceType a service type that is specified in {@link ImsCallProfile}
1570 * {@link ImsCallProfile#SERVICE_TYPE_NONE}
1571 * {@link ImsCallProfile#SERVICE_TYPE_NORMAL}
1572 * {@link ImsCallProfile#SERVICE_TYPE_EMERGENCY}
1573 * @param callType a call type that is specified in {@link ImsCallProfile}
1574 * {@link ImsCallProfile#CALL_TYPE_VOICE}
1575 * {@link ImsCallProfile#CALL_TYPE_VT}
1576 * {@link ImsCallProfile#CALL_TYPE_VT_TX}
1577 * {@link ImsCallProfile#CALL_TYPE_VT_RX}
1578 * {@link ImsCallProfile#CALL_TYPE_VT_NODIR}
1579 * {@link ImsCallProfile#CALL_TYPE_VS}
1580 * {@link ImsCallProfile#CALL_TYPE_VS_TX}
1581 * {@link ImsCallProfile#CALL_TYPE_VS_RX}
1582 * @return a {@link ImsCallProfile} object
1583 * @throws ImsException if calling the IMS service results in an error
1584 */
Brad Ebingerb5f30c72017-02-17 14:54:31 -08001585 public ImsCallProfile createCallProfile(int sessionId, int serviceType, int callType)
1586 throws ImsException {
Wink Savilleef36ef62014-06-11 08:39:38 -07001587 checkAndThrowExceptionIfServiceUnavailable();
1588
1589 try {
Brad Ebinger16780ff2017-01-26 11:18:21 -08001590 return mImsServiceProxy.createCallProfile(sessionId, serviceType, callType);
Wink Savilleef36ef62014-06-11 08:39:38 -07001591 } catch (RemoteException e) {
1592 throw new ImsException("createCallProfile()", e,
1593 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1594 }
1595 }
1596
1597 /**
1598 * Creates a {@link ImsCall} to make a call.
1599 *
Brad Ebinger16780ff2017-01-26 11:18:21 -08001600 * @param sessionId a session id which is obtained from {@link ImsManager#open}
Wink Savilleef36ef62014-06-11 08:39:38 -07001601 * @param profile a call profile to make the call
1602 * (it contains service type, call type, media information, etc.)
1603 * @param participants participants to invite the conference call
1604 * @param listener listen to the call events from {@link ImsCall}
1605 * @return a {@link ImsCall} object
1606 * @throws ImsException if calling the IMS service results in an error
1607 */
Brad Ebinger16780ff2017-01-26 11:18:21 -08001608 public ImsCall makeCall(int sessionId, ImsCallProfile profile, String[] callees,
Wink Savilleef36ef62014-06-11 08:39:38 -07001609 ImsCall.Listener listener) throws ImsException {
1610 if (DBG) {
Brad Ebinger16780ff2017-01-26 11:18:21 -08001611 log("makeCall :: sessionId=" + sessionId
fionaxu7b3107c2016-07-06 14:04:06 -07001612 + ", profile=" + profile);
Wink Savilleef36ef62014-06-11 08:39:38 -07001613 }
1614
1615 checkAndThrowExceptionIfServiceUnavailable();
1616
1617 ImsCall call = new ImsCall(mContext, profile);
1618
1619 call.setListener(listener);
Brad Ebinger16780ff2017-01-26 11:18:21 -08001620 ImsCallSession session = createCallSession(sessionId, profile);
Wink Savilleef36ef62014-06-11 08:39:38 -07001621
1622 if ((callees != null) && (callees.length == 1)) {
1623 call.start(session, callees[0]);
1624 } else {
1625 call.start(session, callees);
1626 }
1627
1628 return call;
1629 }
1630
1631 /**
1632 * Creates a {@link ImsCall} to take an incoming call.
1633 *
Brad Ebinger16780ff2017-01-26 11:18:21 -08001634 * @param sessionId a session id which is obtained from {@link ImsManager#open}
Wink Savilleef36ef62014-06-11 08:39:38 -07001635 * @param incomingCallIntent the incoming call broadcast intent
1636 * @param listener to listen to the call events from {@link ImsCall}
1637 * @return a {@link ImsCall} object
1638 * @throws ImsException if calling the IMS service results in an error
1639 */
Brad Ebinger16780ff2017-01-26 11:18:21 -08001640 public ImsCall takeCall(int sessionId, Intent incomingCallIntent,
Wink Savilleef36ef62014-06-11 08:39:38 -07001641 ImsCall.Listener listener) throws ImsException {
1642 if (DBG) {
Brad Ebinger16780ff2017-01-26 11:18:21 -08001643 log("takeCall :: sessionId=" + sessionId
Wink Savilleef36ef62014-06-11 08:39:38 -07001644 + ", incomingCall=" + incomingCallIntent);
1645 }
1646
1647 checkAndThrowExceptionIfServiceUnavailable();
1648
1649 if (incomingCallIntent == null) {
1650 throw new ImsException("Can't retrieve session with null intent",
1651 ImsReasonInfo.CODE_LOCAL_ILLEGAL_ARGUMENT);
1652 }
1653
Brad Ebinger16780ff2017-01-26 11:18:21 -08001654 int incomingServiceId = getImsSessionId(incomingCallIntent);
Wink Savilleef36ef62014-06-11 08:39:38 -07001655
Brad Ebinger16780ff2017-01-26 11:18:21 -08001656 if (sessionId != incomingServiceId) {
Wink Savilleef36ef62014-06-11 08:39:38 -07001657 throw new ImsException("Service id is mismatched in the incoming call intent",
1658 ImsReasonInfo.CODE_LOCAL_ILLEGAL_ARGUMENT);
1659 }
1660
1661 String callId = getCallId(incomingCallIntent);
1662
1663 if (callId == null) {
1664 throw new ImsException("Call ID missing in the incoming call intent",
1665 ImsReasonInfo.CODE_LOCAL_ILLEGAL_ARGUMENT);
1666 }
1667
1668 try {
Brad Ebinger16780ff2017-01-26 11:18:21 -08001669 IImsCallSession session = mImsServiceProxy.getPendingCallSession(sessionId, callId);
Wink Savilleef36ef62014-06-11 08:39:38 -07001670
1671 if (session == null) {
1672 throw new ImsException("No pending session for the call",
1673 ImsReasonInfo.CODE_LOCAL_NO_PENDING_CALL);
1674 }
1675
1676 ImsCall call = new ImsCall(mContext, session.getCallProfile());
1677
1678 call.attachSession(new ImsCallSession(session));
1679 call.setListener(listener);
1680
1681 return call;
1682 } catch (Throwable t) {
1683 throw new ImsException("takeCall()", t, ImsReasonInfo.CODE_UNSPECIFIED);
1684 }
1685 }
1686
1687 /**
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -05001688 * Gets the config interface to get/set service/capability parameters.
1689 *
1690 * @return the ImsConfig instance.
1691 * @throws ImsException if getting the setting interface results in an error.
1692 */
1693 public ImsConfig getConfigInterface() throws ImsException {
Brad Ebinger138b4a62017-06-20 16:29:50 -07001694 if (mConfig != null && mConfig.isBinderAlive()) {
1695 return mConfig;
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -05001696 }
Brad Ebinger138b4a62017-06-20 16:29:50 -07001697
1698 checkAndThrowExceptionIfServiceUnavailable();
1699 try {
1700 IImsConfig config = mImsServiceProxy.getConfigInterface();
1701 if (config == null) {
1702 throw new ImsException("getConfigInterface()",
1703 ImsReasonInfo.CODE_LOCAL_SERVICE_UNAVAILABLE);
1704 }
1705 mConfig = new ImsConfig(config, mContext);
1706 } catch (RemoteException e) {
1707 throw new ImsException("getConfigInterface()", e,
1708 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1709 }
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -05001710 return mConfig;
1711 }
1712
Hall Liue511a202017-08-17 15:49:58 -07001713 /**
1714 * Set the TTY mode. This is the actual tty mode (varies depending on peripheral status)
1715 */
1716 public void setTtyMode(int ttyMode) throws ImsException {
Brad Ebinger479f52c2017-08-28 13:19:22 -07001717 if (!getBooleanCarrierConfig(
Hall Liue511a202017-08-17 15:49:58 -07001718 CarrierConfigManager.KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL)) {
1719 setAdvanced4GMode((ttyMode == TelecomManager.TTY_MODE_OFF) &&
Brad Ebinger479f52c2017-08-28 13:19:22 -07001720 isEnhanced4gLteModeSettingEnabledByUser());
Hall Liue511a202017-08-17 15:49:58 -07001721 }
1722 }
1723
1724 /**
1725 * Sets the UI TTY mode. This is the preferred TTY mode that the user sets in the call
1726 * settings screen.
1727 */
Brad Ebingerb5f30c72017-02-17 14:54:31 -08001728 public void setUiTTYMode(Context context, int uiTtyMode, Message onComplete)
Shriram Ganeshc403b7b2014-08-14 14:18:57 +05301729 throws ImsException {
1730
Etan Cohen82f78122014-12-15 10:10:14 -08001731 checkAndThrowExceptionIfServiceUnavailable();
Shriram Ganeshc403b7b2014-08-14 14:18:57 +05301732
Etan Cohen82f78122014-12-15 10:10:14 -08001733 try {
Brad Ebingerb5f30c72017-02-17 14:54:31 -08001734 mImsServiceProxy.setUiTTYMode(uiTtyMode, onComplete);
Etan Cohen82f78122014-12-15 10:10:14 -08001735 } catch (RemoteException e) {
1736 throw new ImsException("setTTYMode()", e,
1737 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1738 }
Shriram Ganeshc403b7b2014-08-14 14:18:57 +05301739 }
1740
Naveen Kalla525c3a22017-02-06 14:46:42 -08001741 private ImsReasonInfo makeACopy(ImsReasonInfo imsReasonInfo) {
1742 Parcel p = Parcel.obtain();
1743 imsReasonInfo.writeToParcel(p, 0);
1744 p.setDataPosition(0);
1745 ImsReasonInfo clonedReasonInfo = ImsReasonInfo.CREATOR.createFromParcel(p);
1746 p.recycle();
1747 return clonedReasonInfo;
1748 }
1749
1750 /**
1751 * Get Recent IMS Disconnect Reasons.
1752 *
1753 * @return ArrayList of ImsReasonInfo objects. MAX size of the arraylist
1754 * is MAX_RECENT_DISCONNECT_REASONS. The objects are in the
1755 * chronological order.
1756 */
1757 public ArrayList<ImsReasonInfo> getRecentImsDisconnectReasons() {
1758 ArrayList<ImsReasonInfo> disconnectReasons = new ArrayList<>();
1759
1760 for (ImsReasonInfo reason : mRecentDisconnectReasons) {
1761 disconnectReasons.add(makeACopy(reason));
1762 }
1763 return disconnectReasons;
1764 }
Brad Ebinger16417b42017-03-07 13:48:50 -08001765
Brad Ebinger16780ff2017-01-26 11:18:21 -08001766 public int getImsServiceStatus() throws ImsException {
Brad Ebinger16780ff2017-01-26 11:18:21 -08001767 return mImsServiceProxy.getFeatureStatus();
1768 }
Naveen Kalla525c3a22017-02-06 14:46:42 -08001769
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -05001770 /**
Junda Liue7663c02015-06-23 11:16:26 -07001771 * Get the boolean config from carrier config manager.
1772 *
Brad Ebinger16417b42017-03-07 13:48:50 -08001773 * @param key config key defined in CarrierConfigManager
1774 * @return boolean value of corresponding key.
1775 */
Brad Ebinger479f52c2017-08-28 13:19:22 -07001776 private boolean getBooleanCarrierConfig(String key) {
Brad Ebinger16417b42017-03-07 13:48:50 -08001777 int[] subIds = SubscriptionManager.getSubId(mPhoneId);
1778 int subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1779 if (subIds != null && subIds.length >= 1) {
1780 subId = subIds[0];
1781 }
1782 PersistableBundle b = null;
1783 if (mConfigManager != null) {
1784 // If an invalid subId is used, this bundle will contain default values.
1785 b = mConfigManager.getConfigForSubId(subId);
1786 }
1787 if (b != null) {
1788 return b.getBoolean(key);
1789 } else {
1790 // Return static default defined in CarrierConfigManager.
1791 return CarrierConfigManager.getDefaultConfig().getBoolean(key);
1792 }
1793 }
1794
1795 /**
fionaxu5803ef02016-03-08 11:48:48 -08001796 * Get the int config from carrier config manager.
1797 *
Brad Ebinger16417b42017-03-07 13:48:50 -08001798 * @param key config key defined in CarrierConfigManager
1799 * @return integer value of corresponding key.
1800 */
Brad Ebinger479f52c2017-08-28 13:19:22 -07001801 private int getIntCarrierConfig(String key) {
Brad Ebinger16417b42017-03-07 13:48:50 -08001802 int[] subIds = SubscriptionManager.getSubId(mPhoneId);
1803 int subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1804 if (subIds != null && subIds.length >= 1) {
1805 subId = subIds[0];
1806 }
1807 PersistableBundle b = null;
1808 if (mConfigManager != null) {
1809 // If an invalid subId is used, this bundle will contain default values.
1810 b = mConfigManager.getConfigForSubId(subId);
1811 }
1812 if (b != null) {
1813 return b.getInt(key);
1814 } else {
1815 // Return static default defined in CarrierConfigManager.
1816 return CarrierConfigManager.getDefaultConfig().getInt(key);
1817 }
1818 }
1819
1820 /**
Wink Savilleef36ef62014-06-11 08:39:38 -07001821 * Gets the call ID from the specified incoming call broadcast intent.
1822 *
1823 * @param incomingCallIntent the incoming call broadcast intent
1824 * @return the call ID or null if the intent does not contain it
1825 */
1826 private static String getCallId(Intent incomingCallIntent) {
1827 if (incomingCallIntent == null) {
1828 return null;
1829 }
1830
1831 return incomingCallIntent.getStringExtra(EXTRA_CALL_ID);
1832 }
1833
1834 /**
1835 * Gets the service type from the specified incoming call broadcast intent.
1836 *
1837 * @param incomingCallIntent the incoming call broadcast intent
Brad Ebinger16780ff2017-01-26 11:18:21 -08001838 * @return the session identifier or -1 if the intent does not contain it
Wink Savilleef36ef62014-06-11 08:39:38 -07001839 */
Brad Ebinger16780ff2017-01-26 11:18:21 -08001840 private static int getImsSessionId(Intent incomingCallIntent) {
Wink Savilleef36ef62014-06-11 08:39:38 -07001841 if (incomingCallIntent == null) {
1842 return (-1);
1843 }
1844
1845 return incomingCallIntent.getIntExtra(EXTRA_SERVICE_ID, -1);
1846 }
1847
1848 /**
Brad Ebingerb10b61e2017-04-18 11:45:26 -07001849 * Checks to see if the ImsService Binder is connected. If it is not, we try to create the
1850 * connection again.
Wink Savilleef36ef62014-06-11 08:39:38 -07001851 */
1852 private void checkAndThrowExceptionIfServiceUnavailable()
1853 throws ImsException {
Brad Ebinger16780ff2017-01-26 11:18:21 -08001854 if (mImsServiceProxy == null || !mImsServiceProxy.isBinderAlive()) {
1855 createImsService();
Wink Savilleef36ef62014-06-11 08:39:38 -07001856
Brad Ebinger16780ff2017-01-26 11:18:21 -08001857 if (mImsServiceProxy == null) {
Wink Savilleef36ef62014-06-11 08:39:38 -07001858 throw new ImsException("Service is unavailable",
1859 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1860 }
1861 }
1862 }
1863
Brad Ebinger16780ff2017-01-26 11:18:21 -08001864 /**
1865 * Binds the IMS service to make/receive the call. Supports two methods of exposing an
1866 * ImsService:
1867 * 1) com.android.ims.ImsService implementation in ServiceManager (deprecated).
1868 * 2) android.telephony.ims.ImsService implementation through ImsResolver.
1869 */
1870 private void createImsService() {
1871 if (!mConfigDynamicBind) {
Brad Ebinger44fd8af2017-12-14 14:24:02 -08001872 // Deprecated method of binding
Brad Ebinger16780ff2017-01-26 11:18:21 -08001873 Rlog.i(TAG, "Creating ImsService using ServiceManager");
Brad Ebinger44fd8af2017-12-14 14:24:02 -08001874 mImsServiceProxy = ImsServiceProxyCompat.create(mPhoneId, mDeathRecipient);
Brad Ebinger16780ff2017-01-26 11:18:21 -08001875 } else {
1876 Rlog.i(TAG, "Creating ImsService using ImsResolver");
Brad Ebinger44fd8af2017-12-14 14:24:02 -08001877 mImsServiceProxy = ImsServiceProxy.create(mContext, mPhoneId);
Brad Ebinger16780ff2017-01-26 11:18:21 -08001878 }
Brad Ebinger44fd8af2017-12-14 14:24:02 -08001879 // Forwarding interface to tell mStatusCallbacks that the Proxy is unavailable.
1880 mImsServiceProxy.setStatusCallback(new ImsServiceProxy.IFeatureUpdate() {
1881 @Override
1882 public void notifyStateChanged() {
1883 mStatusCallbacks.forEach(ImsServiceProxy.IFeatureUpdate::notifyStateChanged);
1884 }
1885
1886 @Override
1887 public void notifyUnavailable() {
1888 mStatusCallbacks.forEach(ImsServiceProxy.IFeatureUpdate::notifyUnavailable);
1889 }
1890 });
Brad Ebinger9a0280c2017-06-01 15:58:48 -07001891 // We have created a new ImsService connection, signal for re-registration
1892 synchronized (mHasRegisteredLock) {
1893 mHasRegisteredForProxy = false;
1894 }
Etan Cohend7727462014-07-12 14:54:10 -07001895 }
1896
Wink Savilleef36ef62014-06-11 08:39:38 -07001897 /**
1898 * Creates a {@link ImsCallSession} with the specified call profile.
1899 * Use other methods, if applicable, instead of interacting with
1900 * {@link ImsCallSession} directly.
1901 *
1902 * @param serviceId a service id which is obtained from {@link ImsManager#open}
1903 * @param profile a call profile to make the call
1904 */
1905 private ImsCallSession createCallSession(int serviceId,
1906 ImsCallProfile profile) throws ImsException {
1907 try {
Brad Ebingerb10b61e2017-04-18 11:45:26 -07001908 // Throws an exception if the ImsService Feature is not ready to accept commands.
Brad Ebinger16780ff2017-01-26 11:18:21 -08001909 return new ImsCallSession(mImsServiceProxy.createCallSession(serviceId, profile, null));
Wink Savilleef36ef62014-06-11 08:39:38 -07001910 } catch (RemoteException e) {
Brad Ebingerb10b61e2017-04-18 11:45:26 -07001911 Rlog.w(TAG, "CreateCallSession: Error, remote exception: " + e.getMessage());
1912 throw new ImsException("createCallSession()", e,
1913 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1914
Wink Savilleef36ef62014-06-11 08:39:38 -07001915 }
1916 }
1917
Etan Cohena00c9192014-12-23 15:02:29 -08001918 private static void log(String s) {
Wink Savilleef36ef62014-06-11 08:39:38 -07001919 Rlog.d(TAG, s);
1920 }
1921
Etan Cohena00c9192014-12-23 15:02:29 -08001922 private static void loge(String s) {
Wink Savilleef36ef62014-06-11 08:39:38 -07001923 Rlog.e(TAG, s);
1924 }
1925
Etan Cohena00c9192014-12-23 15:02:29 -08001926 private static void loge(String s, Throwable t) {
Wink Savilleef36ef62014-06-11 08:39:38 -07001927 Rlog.e(TAG, s, t);
1928 }
1929
1930 /**
ram7da5a112014-07-16 20:59:27 +05301931 * Used for turning on IMS.if its off already
1932 */
Etan Cohen82f78122014-12-15 10:10:14 -08001933 private void turnOnIms() throws ImsException {
Etan Cohen0c9c09e2014-07-25 11:09:12 -07001934 checkAndThrowExceptionIfServiceUnavailable();
1935
ram7da5a112014-07-16 20:59:27 +05301936 try {
Brad Ebingerb5f30c72017-02-17 14:54:31 -08001937 mImsServiceProxy.turnOnIms();
ram7da5a112014-07-16 20:59:27 +05301938 } catch (RemoteException e) {
1939 throw new ImsException("turnOnIms() ", e, ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1940 }
1941 }
1942
Omkar Kolangade75f3ca32014-10-24 11:10:52 -07001943 private boolean isImsTurnOffAllowed() {
Brad Ebinger479f52c2017-08-28 13:19:22 -07001944 return isTurnOffImsAllowedByPlatform()
1945 && (!isWfcEnabledByPlatform()
1946 || !isWfcEnabledByUser());
Omkar Kolangade75f3ca32014-10-24 11:10:52 -07001947 }
1948
Amit Mahajan9cba36d2016-08-11 10:17:23 -07001949 private void setLteFeatureValues(boolean turnOn) {
1950 log("setLteFeatureValues: " + turnOn);
Omkar Kolangade75f3ca32014-10-24 11:10:52 -07001951 try {
1952 ImsConfig config = getConfigInterface();
Amit Mahajan9cba36d2016-08-11 10:17:23 -07001953 if (config != null) {
Omkar Kolangade75f3ca32014-10-24 11:10:52 -07001954 config.setFeatureValue(ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_LTE,
Pavel Zhamaitsiakf4b90322016-01-26 14:34:09 -08001955 TelephonyManager.NETWORK_TYPE_LTE, turnOn ? 1 : 0, mImsConfigListener);
Pavel Zhamaitsiakff29b9d2016-04-15 12:16:57 -07001956
Brad Ebinger479f52c2017-08-28 13:19:22 -07001957 if (isVolteEnabledByPlatform()) {
1958 boolean ignoreDataEnabledChanged = getBooleanCarrierConfig(
Jack Yu57781852016-11-16 17:20:38 -08001959 CarrierConfigManager.KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS);
Brad Ebinger479f52c2017-08-28 13:19:22 -07001960 boolean enableViLte = turnOn && isVtEnabledByUser() &&
Jack Yu57781852016-11-16 17:20:38 -08001961 (ignoreDataEnabledChanged || isDataEnabled());
Pavel Zhamaitsiakff29b9d2016-04-15 12:16:57 -07001962 config.setFeatureValue(ImsConfig.FeatureConstants.FEATURE_TYPE_VIDEO_OVER_LTE,
1963 TelephonyManager.NETWORK_TYPE_LTE,
1964 enableViLte ? 1 : 0,
1965 mImsConfigListener);
1966 }
Etan Cohenb651fa52014-10-22 10:51:29 -07001967 }
Omkar Kolangade75f3ca32014-10-24 11:10:52 -07001968 } catch (ImsException e) {
Amit Mahajan9cba36d2016-08-11 10:17:23 -07001969 loge("setLteFeatureValues: exception ", e);
Etan Cohencfc784d2014-08-07 18:40:31 -07001970 }
Amit Mahajan9cba36d2016-08-11 10:17:23 -07001971 }
1972
1973 private void setAdvanced4GMode(boolean turnOn) throws ImsException {
1974 checkAndThrowExceptionIfServiceUnavailable();
1975
1976 // if turnOn: first set feature values then call turnOnIms()
1977 // if turnOff: only set feature values if IMS turn off is not allowed. If turn off is
1978 // allowed, first call turnOffIms() then set feature values
Etan Cohencfc784d2014-08-07 18:40:31 -07001979 if (turnOn) {
Amit Mahajan9cba36d2016-08-11 10:17:23 -07001980 setLteFeatureValues(turnOn);
1981 log("setAdvanced4GMode: turnOnIms");
Etan Cohencfc784d2014-08-07 18:40:31 -07001982 turnOnIms();
Amit Mahajan9cba36d2016-08-11 10:17:23 -07001983 } else {
1984 if (isImsTurnOffAllowed()) {
1985 log("setAdvanced4GMode: turnOffIms");
1986 turnOffIms();
1987 }
1988 setLteFeatureValues(turnOn);
Etan Cohencfc784d2014-08-07 18:40:31 -07001989 }
1990 }
1991
ram7da5a112014-07-16 20:59:27 +05301992 /**
1993 * Used for turning off IMS completely in order to make the device CSFB'ed.
1994 * Once turned off, all calls will be over CS.
1995 */
Etan Cohen82f78122014-12-15 10:10:14 -08001996 private void turnOffIms() throws ImsException {
Etan Cohen0c9c09e2014-07-25 11:09:12 -07001997 checkAndThrowExceptionIfServiceUnavailable();
1998
ram7da5a112014-07-16 20:59:27 +05301999 try {
Brad Ebingerb5f30c72017-02-17 14:54:31 -08002000 mImsServiceProxy.turnOffIms();
ram7da5a112014-07-16 20:59:27 +05302001 } catch (RemoteException e) {
2002 throw new ImsException("turnOffIms() ", e, ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
2003 }
2004 }
2005
Naveen Kalla525c3a22017-02-06 14:46:42 -08002006 private void addToRecentDisconnectReasons(ImsReasonInfo reason) {
2007 if (reason == null) return;
2008 while (mRecentDisconnectReasons.size() >= MAX_RECENT_DISCONNECT_REASONS) {
2009 mRecentDisconnectReasons.removeFirst();
2010 }
2011 mRecentDisconnectReasons.addLast(reason);
2012 }
2013
ram7da5a112014-07-16 20:59:27 +05302014 /**
Wink Savilleef36ef62014-06-11 08:39:38 -07002015 * Death recipient class for monitoring IMS service.
2016 */
2017 private class ImsServiceDeathRecipient implements IBinder.DeathRecipient {
2018 @Override
2019 public void binderDied() {
Brad Ebinger16780ff2017-01-26 11:18:21 -08002020 mImsServiceProxy = null;
Wink Savilleef36ef62014-06-11 08:39:38 -07002021 mUt = null;
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -05002022 mConfig = null;
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -07002023 mEcbm = null;
Tyler Gunn4d128b62016-04-13 15:44:38 -07002024 mMultiEndpoint = null;
Wink Savilleef36ef62014-06-11 08:39:38 -07002025 }
2026 }
2027
2028 /**
Brad Ebinger57b11892017-06-13 16:21:35 -07002029 * Stub implementation of the Registration listener that provides no functionality.
2030 */
2031 private class ImsRegistrationListenerBase extends IImsRegistrationListener.Stub {
2032
2033 @Override
2034 public void registrationConnected() throws RemoteException {
2035 }
2036
2037 @Override
2038 public void registrationProgressing() throws RemoteException {
2039 }
2040
2041 @Override
2042 public void registrationConnectedWithRadioTech(int imsRadioTech) throws RemoteException {
2043 }
2044
2045 @Override
2046 public void registrationProgressingWithRadioTech(int imsRadioTech) throws RemoteException {
2047 }
2048
2049 @Override
2050 public void registrationDisconnected(ImsReasonInfo imsReasonInfo) throws RemoteException {
2051 }
2052
2053 @Override
2054 public void registrationResumed() throws RemoteException {
2055 }
2056
2057 @Override
2058 public void registrationSuspended() throws RemoteException {
2059 }
2060
2061 @Override
2062 public void registrationServiceCapabilityChanged(int serviceClass, int event)
2063 throws RemoteException {
2064 }
2065
2066 @Override
2067 public void registrationFeatureCapabilityChanged(int serviceClass, int[] enabledFeatures,
2068 int[] disabledFeatures) throws RemoteException {
2069 }
2070
2071 @Override
2072 public void voiceMessageCountUpdate(int count) throws RemoteException {
2073 }
2074
2075 @Override
2076 public void registrationAssociatedUriChanged(Uri[] uris) throws RemoteException {
2077 }
2078
2079 @Override
2080 public void registrationChangeFailed(int targetAccessTech, ImsReasonInfo imsReasonInfo)
2081 throws RemoteException {
2082 }
2083 }
2084
2085 /**
Wink Savilleef36ef62014-06-11 08:39:38 -07002086 * Adapter class for {@link IImsRegistrationListener}.
2087 */
Naveen Kalla196fd3b2017-02-14 14:55:24 -08002088 private class ImsRegistrationListenerProxy extends IImsRegistrationListener.Stub {
Wink Savilleef36ef62014-06-11 08:39:38 -07002089
Omkar Kolangadea7ced642015-05-04 17:55:13 -07002090 @Deprecated
Wink Savilleef36ef62014-06-11 08:39:38 -07002091 public void registrationConnected() {
2092 if (DBG) {
2093 log("registrationConnected ::");
2094 }
2095
Brad Ebinger9a0280c2017-06-01 15:58:48 -07002096 synchronized (mRegistrationListeners) {
2097 mRegistrationListeners.forEach(l -> l.onImsConnected(
2098 ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN));
Wink Savilleef36ef62014-06-11 08:39:38 -07002099 }
2100 }
2101
Omkar Kolangadea7ced642015-05-04 17:55:13 -07002102 @Deprecated
Rekha Kumar14631742015-02-04 10:47:00 -08002103 public void registrationProgressing() {
Wink Savilleef36ef62014-06-11 08:39:38 -07002104 if (DBG) {
Rekha Kumar14631742015-02-04 10:47:00 -08002105 log("registrationProgressing ::");
Wink Savilleef36ef62014-06-11 08:39:38 -07002106 }
2107
Brad Ebinger9a0280c2017-06-01 15:58:48 -07002108 synchronized (mRegistrationListeners) {
2109 mRegistrationListeners.forEach(l -> l.onImsProgressing(
2110 ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN));
Rekha Kumar14631742015-02-04 10:47:00 -08002111 }
2112 }
2113
2114 @Override
Omkar Kolangadea7ced642015-05-04 17:55:13 -07002115 public void registrationConnectedWithRadioTech(int imsRadioTech) {
2116 // Note: imsRadioTech value maps to RIL_RADIO_TECHNOLOGY
2117 // values in ServiceState.java.
2118 if (DBG) {
2119 log("registrationConnectedWithRadioTech :: imsRadioTech=" + imsRadioTech);
2120 }
2121
Brad Ebinger9a0280c2017-06-01 15:58:48 -07002122 synchronized (mRegistrationListeners) {
2123 mRegistrationListeners.forEach(l -> l.onImsConnected(imsRadioTech));
Omkar Kolangadea7ced642015-05-04 17:55:13 -07002124 }
2125 }
2126
2127 @Override
2128 public void registrationProgressingWithRadioTech(int imsRadioTech) {
2129 // Note: imsRadioTech value maps to RIL_RADIO_TECHNOLOGY
2130 // values in ServiceState.java.
2131 if (DBG) {
2132 log("registrationProgressingWithRadioTech :: imsRadioTech=" + imsRadioTech);
2133 }
2134
Brad Ebinger9a0280c2017-06-01 15:58:48 -07002135 synchronized (mRegistrationListeners) {
2136 mRegistrationListeners.forEach(l -> l.onImsProgressing(imsRadioTech));
Omkar Kolangadea7ced642015-05-04 17:55:13 -07002137 }
2138 }
2139
2140 @Override
Rekha Kumar14631742015-02-04 10:47:00 -08002141 public void registrationDisconnected(ImsReasonInfo imsReasonInfo) {
2142 if (DBG) {
2143 log("registrationDisconnected :: imsReasonInfo" + imsReasonInfo);
2144 }
2145
Naveen Kalla525c3a22017-02-06 14:46:42 -08002146 addToRecentDisconnectReasons(imsReasonInfo);
Brad Ebinger9a0280c2017-06-01 15:58:48 -07002147 synchronized (mRegistrationListeners) {
2148 mRegistrationListeners.forEach(l -> l.onImsDisconnected(imsReasonInfo));
Wink Savilleef36ef62014-06-11 08:39:38 -07002149 }
2150 }
2151
2152 @Override
2153 public void registrationResumed() {
2154 if (DBG) {
2155 log("registrationResumed ::");
2156 }
2157
Brad Ebinger9a0280c2017-06-01 15:58:48 -07002158 synchronized (mRegistrationListeners) {
2159 mRegistrationListeners.forEach(ImsConnectionStateListener::onImsResumed);
Wink Savilleef36ef62014-06-11 08:39:38 -07002160 }
2161 }
2162
2163 @Override
2164 public void registrationSuspended() {
2165 if (DBG) {
2166 log("registrationSuspended ::");
2167 }
2168
Brad Ebinger9a0280c2017-06-01 15:58:48 -07002169 synchronized (mRegistrationListeners) {
2170 mRegistrationListeners.forEach(ImsConnectionStateListener::onImsSuspended);
Wink Savilleef36ef62014-06-11 08:39:38 -07002171 }
2172 }
2173
2174 @Override
2175 public void registrationServiceCapabilityChanged(int serviceClass, int event) {
2176 log("registrationServiceCapabilityChanged :: serviceClass=" +
2177 serviceClass + ", event=" + event);
2178
Brad Ebinger9a0280c2017-06-01 15:58:48 -07002179 synchronized (mRegistrationListeners) {
2180 mRegistrationListeners.forEach(l -> l.onImsConnected(
2181 ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN));
Wink Savilleef36ef62014-06-11 08:39:38 -07002182 }
2183 }
ram7da5a112014-07-16 20:59:27 +05302184
2185 @Override
2186 public void registrationFeatureCapabilityChanged(int serviceClass,
2187 int[] enabledFeatures, int[] disabledFeatures) {
2188 log("registrationFeatureCapabilityChanged :: serviceClass=" +
2189 serviceClass);
Brad Ebinger9a0280c2017-06-01 15:58:48 -07002190
2191 synchronized (mRegistrationListeners) {
2192 mRegistrationListeners.forEach(l -> l.onFeatureCapabilityChanged(serviceClass,
2193 enabledFeatures, disabledFeatures));
Libin.Tang@motorola.come2296782014-08-19 14:20:01 -05002194 }
ram7da5a112014-07-16 20:59:27 +05302195 }
2196
Shriram Ganeshd3adfad2015-05-31 10:06:15 -07002197 @Override
2198 public void voiceMessageCountUpdate(int count) {
2199 log("voiceMessageCountUpdate :: count=" + count);
2200
Brad Ebinger9a0280c2017-06-01 15:58:48 -07002201 synchronized (mRegistrationListeners) {
2202 mRegistrationListeners.forEach(l -> l.onVoiceMessageCountChanged(count));
Shriram Ganeshd3adfad2015-05-31 10:06:15 -07002203 }
2204 }
2205
Pavel Zhamaitsiak4de9cbb2016-02-11 17:21:05 -08002206 @Override
2207 public void registrationAssociatedUriChanged(Uri[] uris) {
2208 if (DBG) log("registrationAssociatedUriChanged ::");
2209
Brad Ebinger9a0280c2017-06-01 15:58:48 -07002210 synchronized (mRegistrationListeners) {
2211 mRegistrationListeners.forEach(l -> l.registrationAssociatedUriChanged(uris));
Pavel Zhamaitsiak4de9cbb2016-02-11 17:21:05 -08002212 }
2213 }
Meng Wangbb98b9b2016-12-07 16:27:15 -08002214
2215 @Override
2216 public void registrationChangeFailed(int targetAccessTech, ImsReasonInfo imsReasonInfo) {
2217 if (DBG) log("registrationChangeFailed :: targetAccessTech=" + targetAccessTech +
2218 ", imsReasonInfo=" + imsReasonInfo);
2219
Brad Ebinger9a0280c2017-06-01 15:58:48 -07002220 synchronized (mRegistrationListeners) {
2221 mRegistrationListeners.forEach(l -> l.onRegistrationChangeFailed(targetAccessTech,
2222 imsReasonInfo));
Meng Wangbb98b9b2016-12-07 16:27:15 -08002223 }
2224 }
Wink Savilleef36ef62014-06-11 08:39:38 -07002225 }
Tyler Gunn4d128b62016-04-13 15:44:38 -07002226
Brad Ebinger44fd8af2017-12-14 14:24:02 -08002227 // New API for Registration, uses ImsConnectionStateListener for backwards compatibility with
2228 // deprecated APIs.
2229 private class ImsRegistrationCallback extends IImsRegistrationCallback.Stub {
2230
2231 @Override
2232 public void onRegistered(int imsRadioTech) {
2233 if (DBG) log("onRegistered ::");
2234
2235 synchronized (mRegistrationListeners) {
2236 mRegistrationListeners.forEach(l -> l.onRegistered(imsRadioTech));
2237 }
2238 }
2239
2240 @Override
2241 public void onRegistering(int imsRadioTech) {
2242 if (DBG) log("onRegistering ::");
2243
2244 synchronized (mRegistrationListeners) {
2245 mRegistrationListeners.forEach(l -> l.onRegistering(imsRadioTech));
2246 }
2247 }
2248
2249 @Override
2250 public void onDeregistered(ImsReasonInfo imsReasonInfo) {
2251 if (DBG) log("onDeregistered ::");
2252
2253 synchronized (mRegistrationListeners) {
2254 mRegistrationListeners.forEach(l -> l.onDeregistered(imsReasonInfo));
2255 }
2256 }
2257
2258 @Override
2259 public void onTechnologyChangeFailed(int targetRadioTech, ImsReasonInfo imsReasonInfo) {
2260 if (DBG) log("onTechnologyChangeFailed :: targetAccessTech=" + targetRadioTech +
2261 ", imsReasonInfo=" + imsReasonInfo);
2262
2263 synchronized (mRegistrationListeners) {
2264 mRegistrationListeners.forEach(l -> l.onTechnologyChangeFailed(targetRadioTech,
2265 imsReasonInfo));
2266 }
2267 }
2268
2269 @Override
2270 public void onSubscriberAssociatedUriChanged(Uri[] uris) {
2271 if (DBG) log("onSubscriberAssociatedUriChanged");
2272 synchronized (mRegistrationListeners) {
2273 mRegistrationListeners.forEach(l -> l.onSubscriberAssociatedUriChanged(uris));
2274 }
2275 }
2276 }
2277
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -07002278 /**
2279 * Gets the ECBM interface to request ECBM exit.
2280 *
2281 * @param serviceId a service id which is obtained from {@link ImsManager#open}
2282 * @return the ECBM interface instance
2283 * @throws ImsException if getting the ECBM interface results in an error
2284 */
2285 public ImsEcbm getEcbmInterface(int serviceId) throws ImsException {
Brad Ebinger138b4a62017-06-20 16:29:50 -07002286 if (mEcbm != null && mEcbm.isBinderAlive()) {
2287 return mEcbm;
2288 }
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -07002289
Brad Ebinger138b4a62017-06-20 16:29:50 -07002290 checkAndThrowExceptionIfServiceUnavailable();
2291 try {
2292 IImsEcbm iEcbm = mImsServiceProxy.getEcbmInterface();
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -07002293
Brad Ebinger138b4a62017-06-20 16:29:50 -07002294 if (iEcbm == null) {
2295 throw new ImsException("getEcbmInterface()",
2296 ImsReasonInfo.CODE_ECBM_NOT_SUPPORTED);
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -07002297 }
Brad Ebinger138b4a62017-06-20 16:29:50 -07002298 mEcbm = new ImsEcbm(iEcbm);
2299 } catch (RemoteException e) {
2300 throw new ImsException("getEcbmInterface()", e,
2301 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -07002302 }
2303 return mEcbm;
2304 }
Pavel Zhamaitsiak8c065f52015-11-10 14:36:44 -08002305
Mohamed Abdalkader4d68a982018-01-10 13:29:26 -08002306 public void sendSms(int token, int messageRef, String format, String smsc, boolean isRetry,
2307 byte[] pdu) throws ImsException {
2308 try {
2309 mImsServiceProxy.sendSms(token, messageRef, format, smsc, isRetry, pdu);
2310 } catch (RemoteException e) {
2311 throw new ImsException("sendSms()", e, ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
2312 }
2313 }
2314
2315 public void acknowledgeSms(int token, int messageRef, int result) throws ImsException {
2316 try {
2317 mImsServiceProxy.acknowledgeSms(token, messageRef, result);
2318 } catch (RemoteException e) {
2319 throw new ImsException("acknowledgeSms()", e,
2320 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
2321 }
2322 }
2323
2324 public void acknowledgeSmsReport(int token, int messageRef, int result) throws ImsException{
2325 try {
2326 mImsServiceProxy.acknowledgeSmsReport(token, messageRef, result);
2327 } catch (RemoteException e) {
2328 throw new ImsException("acknowledgeSmsReport()", e,
2329 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
2330 }
2331 }
2332
2333 public String getSmsFormat() throws ImsException{
2334 try {
2335 return mImsServiceProxy.getSmsFormat();
2336 } catch (RemoteException e) {
2337 throw new ImsException("getSmsFormat()", e,
2338 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
2339 }
2340 }
2341
2342 public void setSmsListener(IImsSmsListener listener) throws ImsException {
2343 try {
2344 mImsServiceProxy.setSmsListener(listener);
2345 } catch (RemoteException e) {
2346 throw new ImsException("setSmsListener()", e,
2347 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
2348 }
2349 }
Pavel Zhamaitsiak8c065f52015-11-10 14:36:44 -08002350 /**
Tyler Gunn4d128b62016-04-13 15:44:38 -07002351 * Gets the Multi-Endpoint interface to subscribe to multi-enpoint notifications..
2352 *
2353 * @param serviceId a service id which is obtained from {@link ImsManager#open}
2354 * @return the multi-endpoint interface instance
2355 * @throws ImsException if getting the multi-endpoint interface results in an error
2356 */
2357 public ImsMultiEndpoint getMultiEndpointInterface(int serviceId) throws ImsException {
Brad Ebinger138b4a62017-06-20 16:29:50 -07002358 if (mMultiEndpoint != null && mMultiEndpoint.isBinderAlive()) {
2359 return mMultiEndpoint;
Tyler Gunn4d128b62016-04-13 15:44:38 -07002360 }
Brad Ebinger138b4a62017-06-20 16:29:50 -07002361
2362 checkAndThrowExceptionIfServiceUnavailable();
2363 try {
2364 IImsMultiEndpoint iImsMultiEndpoint = mImsServiceProxy.getMultiEndpointInterface();
2365
2366 if (iImsMultiEndpoint == null) {
2367 throw new ImsException("getMultiEndpointInterface()",
2368 ImsReasonInfo.CODE_MULTIENDPOINT_NOT_SUPPORTED);
2369 }
2370 mMultiEndpoint = new ImsMultiEndpoint(iImsMultiEndpoint);
2371 } catch (RemoteException e) {
2372 throw new ImsException("getMultiEndpointInterface()", e,
2373 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
2374 }
2375
Tyler Gunn4d128b62016-04-13 15:44:38 -07002376 return mMultiEndpoint;
2377 }
2378
2379 /**
Pavel Zhamaitsiak8c065f52015-11-10 14:36:44 -08002380 * Resets ImsManager settings back to factory defaults.
2381 *
Brad Ebinger479f52c2017-08-28 13:19:22 -07002382 * @deprecated Doesn't support MSIM devices. Use {@link #factoryReset()} instead.
Brad Ebinger16417b42017-03-07 13:48:50 -08002383 *
Pavel Zhamaitsiak8c065f52015-11-10 14:36:44 -08002384 * @hide
2385 */
2386 public static void factoryReset(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -07002387 ImsManager mgr = ImsManager.getInstance(context,
2388 SubscriptionManager.getDefaultVoicePhoneId());
2389 if (mgr != null) {
2390 mgr.factoryReset();
2391 }
2392 loge("factoryReset: ImsManager null.");
Pavel Zhamaitsiak8c065f52015-11-10 14:36:44 -08002393 }
Jack Yu2f102bd2015-12-28 15:31:48 -08002394
Brad Ebinger16417b42017-03-07 13:48:50 -08002395 /**
2396 * Resets ImsManager settings back to factory defaults.
2397 *
2398 * @hide
2399 */
Brad Ebinger479f52c2017-08-28 13:19:22 -07002400 public void factoryReset() {
Brad Ebinger16417b42017-03-07 13:48:50 -08002401 // Set VoLTE to default
Malcolm Chen212ca652017-09-28 17:28:45 -07002402 SubscriptionManager.setSubscriptionProperty(getSubId(),
manabu, shimoda96aee542017-10-06 15:39:36 +09002403 SubscriptionManager.ENHANCED_4G_MODE_ENABLED,
2404 booleanToPropertyString(getBooleanCarrierConfig(
2405 CarrierConfigManager.KEY_ENHANCED_4G_LTE_ON_BY_DEFAULT_BOOL)));
Brad Ebinger16417b42017-03-07 13:48:50 -08002406
2407 // Set VoWiFi to default
Malcolm Chen212ca652017-09-28 17:28:45 -07002408 SubscriptionManager.setSubscriptionProperty(getSubId(),
2409 SubscriptionManager.WFC_IMS_ENABLED,
2410 booleanToPropertyString(getBooleanCarrierConfig(
2411 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ENABLED_BOOL)));
Brad Ebinger16417b42017-03-07 13:48:50 -08002412
2413 // Set VoWiFi mode to default
Malcolm Chen212ca652017-09-28 17:28:45 -07002414 SubscriptionManager.setSubscriptionProperty(getSubId(),
2415 SubscriptionManager.WFC_IMS_MODE,
2416 Integer.toString(getIntCarrierConfig(
2417 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_MODE_INT)));
Brad Ebinger16417b42017-03-07 13:48:50 -08002418
2419 // Set VoWiFi roaming to default
Malcolm Chen212ca652017-09-28 17:28:45 -07002420 SubscriptionManager.setSubscriptionProperty(getSubId(),
2421 SubscriptionManager.WFC_IMS_ROAMING_ENABLED,
2422 booleanToPropertyString(getBooleanCarrierConfig(
2423 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_ENABLED_BOOL)));
Brad Ebinger16417b42017-03-07 13:48:50 -08002424
2425 // Set VT to default
Malcolm Chen212ca652017-09-28 17:28:45 -07002426 SubscriptionManager.setSubscriptionProperty(getSubId(),
2427 SubscriptionManager.VT_IMS_ENABLED, booleanToPropertyString(true));
Brad Ebinger16417b42017-03-07 13:48:50 -08002428
2429 // Push settings to ImsConfig
Brad Ebinger479f52c2017-08-28 13:19:22 -07002430 updateImsServiceConfig(true);
Brad Ebinger16417b42017-03-07 13:48:50 -08002431 }
2432
Amit Mahajan24f7b162016-07-21 16:33:53 -07002433 private boolean isDataEnabled() {
Malcolm Chend0ef12c2017-12-20 11:38:25 -08002434 return new TelephonyManager(mContext, getSubId()).isMobileDataEnabled();
Amit Mahajan24f7b162016-07-21 16:33:53 -07002435 }
2436
2437 private boolean isVolteProvisioned() {
Malcolm Chen18837ff2017-10-25 17:05:41 -07002438 return getProvisionedBoolNoException(
2439 ImsConfig.ConfigConstants.VLT_SETTING_ENABLED);
Amit Mahajan24f7b162016-07-21 16:33:53 -07002440 }
2441
2442 private boolean isWfcProvisioned() {
Malcolm Chen18837ff2017-10-25 17:05:41 -07002443 return getProvisionedBoolNoException(
2444 ImsConfig.ConfigConstants.VOICE_OVER_WIFI_SETTING_ENABLED);
Amit Mahajan24f7b162016-07-21 16:33:53 -07002445 }
2446
2447 private boolean isVtProvisioned() {
Malcolm Chen18837ff2017-10-25 17:05:41 -07002448 return getProvisionedBoolNoException(
2449 ImsConfig.ConfigConstants.LVC_SETTING_ENABLED);
Jack Yu643ffe42016-07-08 14:25:46 -07002450 }
2451
Malcolm Chen212ca652017-09-28 17:28:45 -07002452 private static String booleanToPropertyString(boolean bool) {
2453 return bool ? "1" : "0";
2454 }
2455
2456
Jack Yu2f102bd2015-12-28 15:31:48 -08002457 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
2458 pw.println("ImsManager:");
2459 pw.println(" mPhoneId = " + mPhoneId);
2460 pw.println(" mConfigUpdated = " + mConfigUpdated);
Brad Ebinger16780ff2017-01-26 11:18:21 -08002461 pw.println(" mImsServiceProxy = " + mImsServiceProxy);
Amit Mahajan24f7b162016-07-21 16:33:53 -07002462 pw.println(" mDataEnabled = " + isDataEnabled());
Brad Ebinger479f52c2017-08-28 13:19:22 -07002463 pw.println(" ignoreDataEnabledChanged = " + getBooleanCarrierConfig(
Jack Yu57781852016-11-16 17:20:38 -08002464 CarrierConfigManager.KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS));
Jack Yu2f102bd2015-12-28 15:31:48 -08002465
Brad Ebinger479f52c2017-08-28 13:19:22 -07002466 pw.println(" isGbaValid = " + isGbaValid());
Jack Yu2f102bd2015-12-28 15:31:48 -08002467 pw.println(" isImsTurnOffAllowed = " + isImsTurnOffAllowed());
Brad Ebinger479f52c2017-08-28 13:19:22 -07002468 pw.println(" isNonTtyOrTtyOnVolteEnabled = " + isNonTtyOrTtyOnVolteEnabled());
Jack Yu2f102bd2015-12-28 15:31:48 -08002469
Brad Ebinger479f52c2017-08-28 13:19:22 -07002470 pw.println(" isVolteEnabledByPlatform = " + isVolteEnabledByPlatform());
2471 pw.println(" isVolteProvisionedOnDevice = " + isVolteProvisionedOnDevice());
Jack Yu2f102bd2015-12-28 15:31:48 -08002472 pw.println(" isEnhanced4gLteModeSettingEnabledByUser = " +
Brad Ebinger479f52c2017-08-28 13:19:22 -07002473 isEnhanced4gLteModeSettingEnabledByUser());
2474 pw.println(" isVtEnabledByPlatform = " + isVtEnabledByPlatform());
2475 pw.println(" isVtEnabledByUser = " + isVtEnabledByUser());
Jack Yu2f102bd2015-12-28 15:31:48 -08002476
Brad Ebinger479f52c2017-08-28 13:19:22 -07002477 pw.println(" isWfcEnabledByPlatform = " + isWfcEnabledByPlatform());
2478 pw.println(" isWfcEnabledByUser = " + isWfcEnabledByUser());
2479 pw.println(" getWfcMode = " + getWfcMode());
2480 pw.println(" isWfcRoamingEnabledByUser = " + isWfcRoamingEnabledByUser());
Jack Yu2f102bd2015-12-28 15:31:48 -08002481
Brad Ebinger479f52c2017-08-28 13:19:22 -07002482 pw.println(" isVtProvisionedOnDevice = " + isVtProvisionedOnDevice());
2483 pw.println(" isWfcProvisionedOnDevice = " + isWfcProvisionedOnDevice());
Jack Yu2f102bd2015-12-28 15:31:48 -08002484 pw.flush();
2485 }
Wink Savilleef36ef62014-06-11 08:39:38 -07002486}