blob: e86bfde7126bd3da23b31b4d9b7b80894384c873 [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;
Mohamed Abdalkadere1453f42018-01-19 19:48:31 -080032import android.telephony.ims.internal.feature.ImsFeature;
33import android.telephony.ims.stub.ImsRegistrationImplBase;
Wink Savilleef36ef62014-06-11 08:39:38 -070034import android.telephony.Rlog;
Meng Wangbb98b9b2016-12-07 16:27:15 -080035import android.telephony.ServiceState;
Etan Cohen82f78122014-12-15 10:10:14 -080036import android.telephony.SubscriptionManager;
Etan Cohencfc784d2014-08-07 18:40:31 -070037import android.telephony.TelephonyManager;
Hall Liue511a202017-08-17 15:49:58 -070038import android.util.Log;
Wink Savilleef36ef62014-06-11 08:39:38 -070039
40import com.android.ims.internal.IImsCallSession;
Naveen Kalla525c3a22017-02-06 14:46:42 -080041import com.android.ims.internal.IImsConfig;
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -070042import com.android.ims.internal.IImsEcbm;
Tyler Gunn4d128b62016-04-13 15:44:38 -070043import com.android.ims.internal.IImsMultiEndpoint;
Brad Ebinger3418c132018-01-18 12:03:33 -080044import com.android.ims.internal.IImsRegistration;
Brad Ebinger44fd8af2017-12-14 14:24:02 -080045import com.android.ims.internal.IImsRegistrationCallback;
Wink Savilleef36ef62014-06-11 08:39:38 -070046import com.android.ims.internal.IImsRegistrationListener;
Mohamed Abdalkader4d68a982018-01-10 13:29:26 -080047import com.android.ims.internal.IImsServiceController;
48import com.android.ims.internal.IImsSmsListener;
Wink Savilleef36ef62014-06-11 08:39:38 -070049import com.android.ims.internal.IImsUt;
50import com.android.ims.internal.ImsCallSession;
Brad Ebinger16780ff2017-01-26 11:18:21 -080051import com.android.internal.annotations.VisibleForTesting;
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -050052
Jack Yu2f102bd2015-12-28 15:31:48 -080053import java.io.FileDescriptor;
54import java.io.PrintWriter;
Naveen Kalla525c3a22017-02-06 14:46:42 -080055import java.util.ArrayList;
Etan Cohend7727462014-07-12 14:54:10 -070056import java.util.HashMap;
Brad Ebinger16780ff2017-01-26 11:18:21 -080057import java.util.HashSet;
Brad Ebinger16780ff2017-01-26 11:18:21 -080058import java.util.Set;
Malcolm Chen18837ff2017-10-25 17:05:41 -070059import java.util.concurrent.ConcurrentLinkedDeque;
Brad Ebinger44fd8af2017-12-14 14:24:02 -080060import java.util.concurrent.CopyOnWriteArraySet;
Etan Cohend7727462014-07-12 14:54:10 -070061
Wink Savilleef36ef62014-06-11 08:39:38 -070062/**
63 * Provides APIs for IMS services, such as initiating IMS calls, and provides access to
64 * the operator's IMS network. This class is the starting point for any IMS actions.
65 * You can acquire an instance of it with {@link #getInstance getInstance()}.</p>
66 * <p>The APIs in this class allows you to:</p>
67 *
68 * @hide
69 */
70public class ImsManager {
Etan Cohen19604c02014-08-11 14:32:57 -070071
Etan Cohenaf55a402014-09-04 22:34:41 -070072 /*
73 * Debug flag to override configuration flag
74 */
Etan Cohenb651fa52014-10-22 10:51:29 -070075 public static final String PROPERTY_DBG_VOLTE_AVAIL_OVERRIDE = "persist.dbg.volte_avail_ovr";
76 public static final int PROPERTY_DBG_VOLTE_AVAIL_OVERRIDE_DEFAULT = 0;
Etan Cohenea2b5832014-10-23 18:50:35 -070077 public static final String PROPERTY_DBG_VT_AVAIL_OVERRIDE = "persist.dbg.vt_avail_ovr";
78 public static final int PROPERTY_DBG_VT_AVAIL_OVERRIDE_DEFAULT = 0;
Etan Cohena00c9192014-12-23 15:02:29 -080079 public static final String PROPERTY_DBG_WFC_AVAIL_OVERRIDE = "persist.dbg.wfc_avail_ovr";
80 public static final int PROPERTY_DBG_WFC_AVAIL_OVERRIDE_DEFAULT = 0;
Meng Wang9352c432016-06-08 14:22:20 -070081 public static final String PROPERTY_DBG_ALLOW_IMS_OFF_OVERRIDE = "persist.dbg.allow_ims_off";
82 public static final int PROPERTY_DBG_ALLOW_IMS_OFF_OVERRIDE_DEFAULT = 0;
Etan Cohenaf55a402014-09-04 22:34:41 -070083
Wink Savilleef36ef62014-06-11 08:39:38 -070084 /**
Wink Savilleef36ef62014-06-11 08:39:38 -070085 * The result code to be sent back with the incoming call {@link PendingIntent}.
86 * @see #open(PendingIntent, ImsConnectionStateListener)
87 */
88 public static final int INCOMING_CALL_RESULT_CODE = 101;
89
90 /**
91 * Key to retrieve the call ID from an incoming call intent.
92 * @see #open(PendingIntent, ImsConnectionStateListener)
93 */
94 public static final String EXTRA_CALL_ID = "android:imsCallID";
95
96 /**
97 * Action to broadcast when ImsService is up.
98 * Internal use only.
Brad Ebinger16780ff2017-01-26 11:18:21 -080099 * @deprecated
Wink Savilleef36ef62014-06-11 08:39:38 -0700100 * @hide
101 */
102 public static final String ACTION_IMS_SERVICE_UP =
103 "com.android.ims.IMS_SERVICE_UP";
104
105 /**
106 * Action to broadcast when ImsService is down.
107 * Internal use only.
Brad Ebinger16780ff2017-01-26 11:18:21 -0800108 * @deprecated
Wink Savilleef36ef62014-06-11 08:39:38 -0700109 * @hide
110 */
111 public static final String ACTION_IMS_SERVICE_DOWN =
112 "com.android.ims.IMS_SERVICE_DOWN";
113
114 /**
Pavel Zhamaitsiak0c2f15c2015-03-12 15:37:54 -0700115 * Action to broadcast when ImsService registration fails.
116 * Internal use only.
117 * @hide
118 */
119 public static final String ACTION_IMS_REGISTRATION_ERROR =
120 "com.android.ims.REGISTRATION_ERROR";
121
122 /**
Etan Cohend7727462014-07-12 14:54:10 -0700123 * Part of the ACTION_IMS_SERVICE_UP or _DOWN intents.
Etan Cohenabbd7882014-09-26 22:35:35 -0700124 * A long value; the phone ID corresponding to the IMS service coming up or down.
Etan Cohend7727462014-07-12 14:54:10 -0700125 * Internal use only.
126 * @hide
127 */
Etan Cohenabbd7882014-09-26 22:35:35 -0700128 public static final String EXTRA_PHONE_ID = "android:phone_id";
Etan Cohend7727462014-07-12 14:54:10 -0700129
130 /**
Wink Savilleef36ef62014-06-11 08:39:38 -0700131 * Action for the incoming call intent for the Phone app.
132 * Internal use only.
133 * @hide
134 */
135 public static final String ACTION_IMS_INCOMING_CALL =
136 "com.android.ims.IMS_INCOMING_CALL";
137
138 /**
139 * Part of the ACTION_IMS_INCOMING_CALL intents.
140 * An integer value; service identifier obtained from {@link ImsManager#open}.
141 * Internal use only.
142 * @hide
143 */
144 public static final String EXTRA_SERVICE_ID = "android:imsServiceId";
145
146 /**
147 * Part of the ACTION_IMS_INCOMING_CALL intents.
148 * An boolean value; Flag to indicate that the incoming call is a normal call or call for USSD.
149 * The value "true" indicates that the incoming call is for USSD.
150 * Internal use only.
151 * @hide
152 */
153 public static final String EXTRA_USSD = "android:ussd";
154
Shriram Ganeshd3adfad2015-05-31 10:06:15 -0700155 /**
156 * Part of the ACTION_IMS_INCOMING_CALL intents.
157 * A boolean value; Flag to indicate whether the call is an unknown
158 * dialing call. Such calls are originated by sending commands (like
159 * AT commands) directly to modem without Android involvement.
160 * Even though they are not incoming calls, they are propagated
161 * to Phone app using same ACTION_IMS_INCOMING_CALL intent.
162 * Internal use only.
163 * @hide
164 */
Anju Mathapati9c033792015-06-16 16:33:16 -0700165 public static final String EXTRA_IS_UNKNOWN_CALL = "android:isUnknown";
Shriram Ganeshd3adfad2015-05-31 10:06:15 -0700166
Malcolm Chen18837ff2017-10-25 17:05:41 -0700167 private static final int SYSTEM_PROPERTY_NOT_SET = -1;
168
169 // -1 indicates a subscriptionProperty value that is never set.
170 private static final int SUB_PROPERTY_NOT_INITIALIZED = -1;
171
Wink Savilleef36ef62014-06-11 08:39:38 -0700172 private static final String TAG = "ImsManager";
173 private static final boolean DBG = true;
174
Wink Saville1e5a38a2014-10-23 10:24:46 -0700175 private static HashMap<Integer, ImsManager> sImsManagerInstances =
176 new HashMap<Integer, ImsManager>();
Etan Cohend7727462014-07-12 14:54:10 -0700177
Wink Savilleef36ef62014-06-11 08:39:38 -0700178 private Context mContext;
Brad Ebinger16417b42017-03-07 13:48:50 -0800179 private CarrierConfigManager mConfigManager;
Etan Cohenabbd7882014-09-26 22:35:35 -0700180 private int mPhoneId;
Brad Ebinger16780ff2017-01-26 11:18:21 -0800181 private final boolean mConfigDynamicBind;
Brad Ebingera7c32432017-11-06 15:19:27 -0800182 private ImsServiceProxy mImsServiceProxy = null;
Wink Savilleef36ef62014-06-11 08:39:38 -0700183 private ImsServiceDeathRecipient mDeathRecipient = new ImsServiceDeathRecipient();
184 // Ut interface for the supplementary service configuration
185 private ImsUt mUt = null;
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -0500186 // Interface to get/set ims config items
187 private ImsConfig mConfig = null;
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -0700188 private boolean mConfigUpdated = false;
Wink Savilleef36ef62014-06-11 08:39:38 -0700189
Pavel Zhamaitsiakf4b90322016-01-26 14:34:09 -0800190 private ImsConfigListener mImsConfigListener;
191
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -0700192 // ECBM interface
193 private ImsEcbm mEcbm = null;
194
Tyler Gunn4d128b62016-04-13 15:44:38 -0700195 private ImsMultiEndpoint mMultiEndpoint = null;
196
Brad Ebinger44fd8af2017-12-14 14:24:02 -0800197 private Set<ImsServiceProxy.IFeatureUpdate> mStatusCallbacks = new CopyOnWriteArraySet<>();
Brad Ebinger16780ff2017-01-26 11:18:21 -0800198
199 // Keep track of the ImsRegistrationListenerProxys that have been created so that we can
200 // remove them from the ImsService.
Brad Ebinger9a0280c2017-06-01 15:58:48 -0700201 private final Set<ImsConnectionStateListener> mRegistrationListeners = new HashSet<>();
202
Brad Ebinger44fd8af2017-12-14 14:24:02 -0800203
204 // Used for compatibility with the old Registration method
205 // TODO: Remove once the compat layer is in place
206 private final ImsRegistrationListenerProxy mImsRegistrationListenerProxy =
Brad Ebinger9a0280c2017-06-01 15:58:48 -0700207 new ImsRegistrationListenerProxy();
Brad Ebinger44fd8af2017-12-14 14:24:02 -0800208 // New API for registration to the ImsService.
209 private final ImsRegistrationCallback mRegistrationCallback = new ImsRegistrationCallback();
210
Brad Ebinger9a0280c2017-06-01 15:58:48 -0700211
212 // When true, we have registered the mRegistrationListenerProxy with the ImsService. Don't do
213 // it again.
214 private boolean mHasRegisteredForProxy = false;
215 private final Object mHasRegisteredLock = new Object();
Brad Ebinger16780ff2017-01-26 11:18:21 -0800216
Amit Mahajan24f7b162016-07-21 16:33:53 -0700217 public static final String TRUE = "true";
218 public static final String FALSE = "false";
Jack Yu643ffe42016-07-08 14:25:46 -0700219
Naveen Kalla525c3a22017-02-06 14:46:42 -0800220 // mRecentDisconnectReasons stores the last 16 disconnect reasons
221 private static final int MAX_RECENT_DISCONNECT_REASONS = 16;
222 private ConcurrentLinkedDeque<ImsReasonInfo> mRecentDisconnectReasons =
223 new ConcurrentLinkedDeque<>();
224
Wink Savilleef36ef62014-06-11 08:39:38 -0700225 /**
226 * Gets a manager instance.
227 *
228 * @param context application context for creating the manager object
Etan Cohenabbd7882014-09-26 22:35:35 -0700229 * @param phoneId the phone ID for the IMS Service
230 * @return the manager instance corresponding to the phoneId
Wink Savilleef36ef62014-06-11 08:39:38 -0700231 */
Etan Cohenabbd7882014-09-26 22:35:35 -0700232 public static ImsManager getInstance(Context context, int phoneId) {
Etan Cohend7727462014-07-12 14:54:10 -0700233 synchronized (sImsManagerInstances) {
Naveen Kalla525c3a22017-02-06 14:46:42 -0800234 if (sImsManagerInstances.containsKey(phoneId)) {
Brad Ebingerff097922017-06-19 15:43:08 -0700235 ImsManager m = sImsManagerInstances.get(phoneId);
236 // May be null for some tests
237 if (m != null) {
238 m.connectIfServiceIsAvailable();
239 }
240 return m;
Naveen Kalla525c3a22017-02-06 14:46:42 -0800241 }
Wink Savilleef36ef62014-06-11 08:39:38 -0700242
Etan Cohenabbd7882014-09-26 22:35:35 -0700243 ImsManager mgr = new ImsManager(context, phoneId);
244 sImsManagerInstances.put(phoneId, mgr);
Etan Cohend7727462014-07-12 14:54:10 -0700245
246 return mgr;
247 }
Wink Savilleef36ef62014-06-11 08:39:38 -0700248 }
249
Etan Cohen45b5f312014-08-19 15:55:08 -0700250 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800251 * Returns the user configuration of Enhanced 4G LTE Mode setting.
252 *
253 * @deprecated Doesn't support MSIM devices. Use
Brad Ebinger479f52c2017-08-28 13:19:22 -0700254 * {@link #isEnhanced4gLteModeSettingEnabledByUser()} instead.
Etan Cohen45b5f312014-08-19 15:55:08 -0700255 */
256 public static boolean isEnhanced4gLteModeSettingEnabledByUser(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700257 ImsManager mgr = ImsManager.getInstance(context,
258 SubscriptionManager.getDefaultVoicePhoneId());
259 if (mgr != null) {
260 return mgr.isEnhanced4gLteModeSettingEnabledByUser();
Sungmin Choi2f1af952016-02-01 17:15:35 +0900261 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700262 loge("isEnhanced4gLteModeSettingEnabledByUser: ImsManager null, returning default value.");
263 return false;
Etan Cohen45b5f312014-08-19 15:55:08 -0700264 }
265
266 /**
manabu, shimoda96aee542017-10-06 15:39:36 +0900267 * Returns the user configuration of Enhanced 4G LTE Mode setting for slot. If the option is
268 * not editable ({@link CarrierConfigManager#KEY_EDITABLE_ENHANCED_4G_LTE_BOOL} is false), or
269 * the setting is not initialized, this method will return default value specified by
270 * {@link CarrierConfigManager#KEY_ENHANCED_4G_LTE_ON_BY_DEFAULT_BOOL}.
271 *
272 * Note that even if the setting was set, it may no longer be editable. If this is the case we
273 * return the default value.
Brad Ebinger16417b42017-03-07 13:48:50 -0800274 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700275 public boolean isEnhanced4gLteModeSettingEnabledByUser() {
Malcolm Chen212ca652017-09-28 17:28:45 -0700276 int setting = SubscriptionManager.getIntegerSubscriptionProperty(
277 getSubId(), SubscriptionManager.ENHANCED_4G_MODE_ENABLED,
278 SUB_PROPERTY_NOT_INITIALIZED, mContext);
manabu, shimoda96aee542017-10-06 15:39:36 +0900279 boolean onByDefault = getBooleanCarrierConfig(
280 CarrierConfigManager.KEY_ENHANCED_4G_LTE_ON_BY_DEFAULT_BOOL);
Malcolm Chen212ca652017-09-28 17:28:45 -0700281
manabu, shimoda96aee542017-10-06 15:39:36 +0900282 // If Enhanced 4G LTE Mode is uneditable or not initialized, we use the default value
283 if (!getBooleanCarrierConfig(CarrierConfigManager.KEY_EDITABLE_ENHANCED_4G_LTE_BOOL)
284 || setting == SUB_PROPERTY_NOT_INITIALIZED) {
285 return onByDefault;
286 } else {
287 return (setting == ImsConfig.FeatureValueConstants.ON);
288 }
Brad Ebinger16417b42017-03-07 13:48:50 -0800289 }
290
291 /**
292 * Change persistent Enhanced 4G LTE Mode setting.
293 *
Brad Ebinger479f52c2017-08-28 13:19:22 -0700294 * @deprecated Doesn't support MSIM devices. Use {@link #setEnhanced4gLteModeSetting(boolean)}
Brad Ebinger16417b42017-03-07 13:48:50 -0800295 * instead.
Etan Cohen82f78122014-12-15 10:10:14 -0800296 */
297 public static void setEnhanced4gLteModeSetting(Context context, boolean enabled) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700298 ImsManager mgr = ImsManager.getInstance(context,
299 SubscriptionManager.getDefaultVoicePhoneId());
300 if (mgr != null) {
301 mgr.setEnhanced4gLteModeSetting(enabled);
Etan Cohen82f78122014-12-15 10:10:14 -0800302 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700303 loge("setEnhanced4gLteModeSetting: ImsManager null, value not set.");
Etan Cohen82f78122014-12-15 10:10:14 -0800304 }
305
306 /**
manabu, shimoda96aee542017-10-06 15:39:36 +0900307 * Change persistent Enhanced 4G LTE Mode setting. If the option is not editable
Brad Ebinger16417b42017-03-07 13:48:50 -0800308 * ({@link CarrierConfigManager#KEY_EDITABLE_ENHANCED_4G_LTE_BOOL} is false), this method will
manabu, shimoda96aee542017-10-06 15:39:36 +0900309 * set the setting to the default value specified by
310 * {@link CarrierConfigManager#KEY_ENHANCED_4G_LTE_ON_BY_DEFAULT_BOOL}.
Brad Ebinger16417b42017-03-07 13:48:50 -0800311 *
312 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700313 public void setEnhanced4gLteModeSetting(boolean enabled) {
manabu, shimoda96aee542017-10-06 15:39:36 +0900314 // If editable=false, we must keep default advanced 4G mode.
315 if (!getBooleanCarrierConfig(CarrierConfigManager.KEY_EDITABLE_ENHANCED_4G_LTE_BOOL)) {
316 enabled = getBooleanCarrierConfig(
317 CarrierConfigManager.KEY_ENHANCED_4G_LTE_ON_BY_DEFAULT_BOOL);
318 }
Brad Ebinger16417b42017-03-07 13:48:50 -0800319
Malcolm Chen212ca652017-09-28 17:28:45 -0700320 int prevSetting = SubscriptionManager.getIntegerSubscriptionProperty(
321 getSubId(), SubscriptionManager.ENHANCED_4G_MODE_ENABLED,
322 SUB_PROPERTY_NOT_INITIALIZED, mContext);
Brad Ebinger16417b42017-03-07 13:48:50 -0800323
manabu, shimoda96aee542017-10-06 15:39:36 +0900324 if (prevSetting != (enabled ?
325 ImsConfig.FeatureValueConstants.ON :
326 ImsConfig.FeatureValueConstants.OFF)) {
Malcolm Chen212ca652017-09-28 17:28:45 -0700327 SubscriptionManager.setSubscriptionProperty(getSubId(),
328 SubscriptionManager.ENHANCED_4G_MODE_ENABLED, booleanToPropertyString(enabled));
329 if (isNonTtyOrTtyOnVolteEnabled()) {
330 try {
331 setAdvanced4GMode(enabled);
332 } catch (ImsException ie) {
333 // do nothing
334 }
Brad Ebinger16417b42017-03-07 13:48:50 -0800335 }
336 }
337 }
338
339 /**
Etan Cohen82f78122014-12-15 10:10:14 -0800340 * Indicates whether the call is non-TTY or if TTY - whether TTY on VoLTE is
341 * supported.
Brad Ebinger16417b42017-03-07 13:48:50 -0800342 * @deprecated Does not support MSIM devices. Please use
Brad Ebinger479f52c2017-08-28 13:19:22 -0700343 * {@link #isNonTtyOrTtyOnVolteEnabled()} instead.
Etan Cohen82f78122014-12-15 10:10:14 -0800344 */
345 public static boolean isNonTtyOrTtyOnVolteEnabled(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700346 ImsManager mgr = ImsManager.getInstance(context,
347 SubscriptionManager.getDefaultVoicePhoneId());
348 if (mgr != null) {
349 return mgr.isNonTtyOrTtyOnVolteEnabled();
350 }
351 loge("isNonTtyOrTtyOnVolteEnabled: ImsManager null, returning default value.");
352 return false;
353 }
354
355 /**
356 * Indicates whether the call is non-TTY or if TTY - whether TTY on VoLTE is
357 * supported on a per slot basis.
358 */
359 public boolean isNonTtyOrTtyOnVolteEnabled() {
360 if (getBooleanCarrierConfig(
fionaxu5803ef02016-03-08 11:48:48 -0800361 CarrierConfigManager.KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL)) {
Etan Cohen82f78122014-12-15 10:10:14 -0800362 return true;
363 }
364
Brad Ebinger479f52c2017-08-28 13:19:22 -0700365 TelecomManager tm = (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
Hall Liue511a202017-08-17 15:49:58 -0700366 if (tm == null) {
367 Log.w(TAG, "isNonTtyOrTtyOnVolteEnabled: telecom not available");
368 return true;
369 }
370 return tm.getCurrentTtyMode() == TelecomManager.TTY_MODE_OFF;
Etan Cohen82f78122014-12-15 10:10:14 -0800371 }
372
373 /**
Etan Cohenea2b5832014-10-23 18:50:35 -0700374 * Returns a platform configuration for VoLTE which may override the user setting.
Brad Ebinger16417b42017-03-07 13:48:50 -0800375 * @deprecated Does not support MSIM devices. Please use
Brad Ebinger479f52c2017-08-28 13:19:22 -0700376 * {@link #isVolteEnabledByPlatform()} instead.
Etan Cohen45b5f312014-08-19 15:55:08 -0700377 */
Etan Cohenea2b5832014-10-23 18:50:35 -0700378 public static boolean isVolteEnabledByPlatform(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700379 ImsManager mgr = ImsManager.getInstance(context,
380 SubscriptionManager.getDefaultVoicePhoneId());
381 if (mgr != null) {
382 return mgr.isVolteEnabledByPlatform();
Etan Cohenaf55a402014-09-04 22:34:41 -0700383 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700384 loge("isVolteEnabledByPlatform: ImsManager null, returning default value.");
385 return false;
Etan Cohenb5388a32014-11-26 11:57:47 -0800386 }
387
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700388 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800389 * Returns a platform configuration for VoLTE which may override the user setting on a per Slot
390 * basis.
391 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700392 public boolean isVolteEnabledByPlatform() {
Malcolm Chen18837ff2017-10-25 17:05:41 -0700393 // We first read the per slot value. If doesn't exist, we read the general value. If still
394 // doesn't exist, we use the hardcoded default value.
395 if (SystemProperties.getInt(
396 PROPERTY_DBG_VOLTE_AVAIL_OVERRIDE + Integer.toString(mPhoneId),
397 SYSTEM_PROPERTY_NOT_SET) == 1 ||
398 SystemProperties.getInt(PROPERTY_DBG_VOLTE_AVAIL_OVERRIDE,
399 SYSTEM_PROPERTY_NOT_SET) == 1) {
Brad Ebinger16417b42017-03-07 13:48:50 -0800400 return true;
401 }
402
403 return mContext.getResources().getBoolean(
404 com.android.internal.R.bool.config_device_volte_available)
Malcolm Chen212ca652017-09-28 17:28:45 -0700405 && getBooleanCarrierConfig(CarrierConfigManager.KEY_CARRIER_VOLTE_AVAILABLE_BOOL)
Brad Ebinger479f52c2017-08-28 13:19:22 -0700406 && isGbaValid();
Brad Ebinger16417b42017-03-07 13:48:50 -0800407 }
408
409 /**
410 * Indicates whether VoLTE is provisioned on device.
411 *
412 * @deprecated Does not support MSIM devices. Please use
Brad Ebinger479f52c2017-08-28 13:19:22 -0700413 * {@link #isVolteProvisionedOnDevice()} instead.
Etan Cohenb5388a32014-11-26 11:57:47 -0800414 */
415 public static boolean isVolteProvisionedOnDevice(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700416 ImsManager mgr = ImsManager.getInstance(context,
417 SubscriptionManager.getDefaultVoicePhoneId());
418 if (mgr != null) {
419 return mgr.isVolteProvisionedOnDevice();
Etan Cohenb5388a32014-11-26 11:57:47 -0800420 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700421 loge("isVolteProvisionedOnDevice: ImsManager null, returning default value.");
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700422 return true;
423 }
424
425 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800426 * Indicates whether VoLTE is provisioned on this slot.
427 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700428 public boolean isVolteProvisionedOnDevice() {
429 if (getBooleanCarrierConfig(
Brad Ebinger16417b42017-03-07 13:48:50 -0800430 CarrierConfigManager.KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL)) {
431 return isVolteProvisioned();
432 }
433
434 return true;
435 }
436
437 /**
Meng Wang54fd41a2017-04-12 11:44:47 -0700438 * Indicates whether VoWifi is provisioned on device.
439 *
440 * When CarrierConfig KEY_CARRIER_VOLTE_OVERRIDE_WFC_PROVISIONING_BOOL is true, and VoLTE is not
441 * provisioned on device, this method returns false.
Brad Ebinger16417b42017-03-07 13:48:50 -0800442 *
443 * @deprecated Does not support MSIM devices. Please use
Brad Ebinger479f52c2017-08-28 13:19:22 -0700444 * {@link #isWfcProvisionedOnDevice()} instead.
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700445 */
446 public static boolean isWfcProvisionedOnDevice(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700447 ImsManager mgr = ImsManager.getInstance(context,
448 SubscriptionManager.getDefaultVoicePhoneId());
449 if (mgr != null) {
450 return mgr.isWfcProvisionedOnDevice();
Meng Wang54fd41a2017-04-12 11:44:47 -0700451 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700452 loge("isWfcProvisionedOnDevice: ImsManager null, returning default value.");
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700453 return true;
454 }
455
456 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800457 * Indicates whether VoWifi is provisioned on slot.
Meng Wang54fd41a2017-04-12 11:44:47 -0700458 *
459 * When CarrierConfig KEY_CARRIER_VOLTE_OVERRIDE_WFC_PROVISIONING_BOOL is true, and VoLTE is not
460 * provisioned on device, this method returns false.
Brad Ebinger16417b42017-03-07 13:48:50 -0800461 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700462 public boolean isWfcProvisionedOnDevice() {
463 if (getBooleanCarrierConfig(
Meng Wang54fd41a2017-04-12 11:44:47 -0700464 CarrierConfigManager.KEY_CARRIER_VOLTE_OVERRIDE_WFC_PROVISIONING_BOOL)) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700465 if (!isVolteProvisionedOnDevice()) {
Meng Wang54fd41a2017-04-12 11:44:47 -0700466 return false;
467 }
468 }
469
Brad Ebinger479f52c2017-08-28 13:19:22 -0700470 if (getBooleanCarrierConfig(
Brad Ebinger16417b42017-03-07 13:48:50 -0800471 CarrierConfigManager.KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL)) {
Meng Wang54fd41a2017-04-12 11:44:47 -0700472 return isWfcProvisioned();
Brad Ebinger16417b42017-03-07 13:48:50 -0800473 }
474
475 return true;
476 }
477
478 /**
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700479 * Indicates whether VT is provisioned on device
Brad Ebinger16417b42017-03-07 13:48:50 -0800480 *
481 * @deprecated Does not support MSIM devices. Please use
Brad Ebinger479f52c2017-08-28 13:19:22 -0700482 * {@link #isVtProvisionedOnDevice()} instead.
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700483 */
484 public static boolean isVtProvisionedOnDevice(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700485 ImsManager mgr = ImsManager.getInstance(context,
486 SubscriptionManager.getDefaultVoicePhoneId());
487 if (mgr != null) {
488 return mgr.isVtProvisionedOnDevice();
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700489 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700490 loge("isVtProvisionedOnDevice: ImsManager null, returning default value.");
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700491 return true;
Etan Cohenb651fa52014-10-22 10:51:29 -0700492 }
493
Etan Cohenea2b5832014-10-23 18:50:35 -0700494 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800495 * Indicates whether VT is provisioned on slot.
496 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700497 public boolean isVtProvisionedOnDevice() {
498 if (getBooleanCarrierConfig(
Brad Ebinger16417b42017-03-07 13:48:50 -0800499 CarrierConfigManager.KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL)) {
500 return isVtProvisioned();
501 }
502
503 return true;
504 }
505
506 /**
Etan Cohenea2b5832014-10-23 18:50:35 -0700507 * Returns a platform configuration for VT which may override the user setting.
508 *
509 * Note: VT presumes that VoLTE is enabled (these are configuration settings
510 * which must be done correctly).
Brad Ebinger16417b42017-03-07 13:48:50 -0800511 *
512 * @deprecated Does not support MSIM devices. Please use
Brad Ebinger479f52c2017-08-28 13:19:22 -0700513 * {@link #isVtEnabledByPlatform()} instead.
Etan Cohenea2b5832014-10-23 18:50:35 -0700514 */
Etan Cohenb651fa52014-10-22 10:51:29 -0700515 public static boolean isVtEnabledByPlatform(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700516 ImsManager mgr = ImsManager.getInstance(context,
517 SubscriptionManager.getDefaultVoicePhoneId());
518 if (mgr != null) {
519 return mgr.isVtEnabledByPlatform();
Etan Cohenea2b5832014-10-23 18:50:35 -0700520 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700521 loge("isVtEnabledByPlatform: ImsManager null, returning default value.");
522 return false;
Etan Cohen45b5f312014-08-19 15:55:08 -0700523 }
524
Etan Cohena00c9192014-12-23 15:02:29 -0800525 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800526 * Returns a platform configuration for VT which may override the user setting.
527 *
528 * Note: VT presumes that VoLTE is enabled (these are configuration settings
529 * which must be done correctly).
530 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700531 public boolean isVtEnabledByPlatform() {
Malcolm Chen18837ff2017-10-25 17:05:41 -0700532 // We first read the per slot value. If doesn't exist, we read the general value. If still
533 // doesn't exist, we use the hardcoded default value.
534 if (SystemProperties.getInt(PROPERTY_DBG_VT_AVAIL_OVERRIDE +
535 Integer.toString(mPhoneId), SYSTEM_PROPERTY_NOT_SET) == 1 ||
536 SystemProperties.getInt(
537 PROPERTY_DBG_VT_AVAIL_OVERRIDE, SYSTEM_PROPERTY_NOT_SET) == 1) {
Brad Ebinger16417b42017-03-07 13:48:50 -0800538 return true;
539 }
540
541 return mContext.getResources().getBoolean(
542 com.android.internal.R.bool.config_device_vt_available) &&
Malcolm Chen212ca652017-09-28 17:28:45 -0700543 getBooleanCarrierConfig(CarrierConfigManager.KEY_CARRIER_VT_AVAILABLE_BOOL) &&
Brad Ebinger479f52c2017-08-28 13:19:22 -0700544 isGbaValid();
Brad Ebinger16417b42017-03-07 13:48:50 -0800545 }
546
547 /**
Etan Cohena7d32e82015-05-04 18:02:09 -0700548 * Returns the user configuration of VT setting
Brad Ebinger16417b42017-03-07 13:48:50 -0800549 * @deprecated Does not support MSIM devices. Please use
Brad Ebinger479f52c2017-08-28 13:19:22 -0700550 * {@link #isVtEnabledByUser()} instead.
Etan Cohena7d32e82015-05-04 18:02:09 -0700551 */
552 public static boolean isVtEnabledByUser(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700553 ImsManager mgr = ImsManager.getInstance(context,
554 SubscriptionManager.getDefaultVoicePhoneId());
555 if (mgr != null) {
556 return mgr.isVtEnabledByUser();
557 }
558 loge("isVtEnabledByUser: ImsManager null, returning default value.");
559 return false;
Etan Cohena7d32e82015-05-04 18:02:09 -0700560 }
561
562 /**
Malcolm Chen212ca652017-09-28 17:28:45 -0700563 * Returns the user configuration of VT setting per slot. If not set, it
564 * returns true as default value.
Brad Ebinger16417b42017-03-07 13:48:50 -0800565 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700566 public boolean isVtEnabledByUser() {
Malcolm Chen212ca652017-09-28 17:28:45 -0700567 int setting = SubscriptionManager.getIntegerSubscriptionProperty(
568 getSubId(), SubscriptionManager.VT_IMS_ENABLED,
569 SUB_PROPERTY_NOT_INITIALIZED, mContext);
570
571 // If it's never set, by default we return true.
manabu, shimoda96aee542017-10-06 15:39:36 +0900572 return (setting == SUB_PROPERTY_NOT_INITIALIZED
573 || setting == ImsConfig.FeatureValueConstants.ON);
Brad Ebinger16417b42017-03-07 13:48:50 -0800574 }
575
576 /**
Etan Cohena7d32e82015-05-04 18:02:09 -0700577 * Change persistent VT enabled setting
Brad Ebinger16417b42017-03-07 13:48:50 -0800578 *
Brad Ebinger479f52c2017-08-28 13:19:22 -0700579 * @deprecated Does not support MSIM devices. Please use {@link #setVtSetting(boolean)} instead.
Etan Cohena7d32e82015-05-04 18:02:09 -0700580 */
581 public static void setVtSetting(Context context, boolean enabled) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700582 ImsManager mgr = ImsManager.getInstance(context,
Etan Cohena7d32e82015-05-04 18:02:09 -0700583 SubscriptionManager.getDefaultVoicePhoneId());
Brad Ebinger479f52c2017-08-28 13:19:22 -0700584 if (mgr != null) {
585 mgr.setVtSetting(enabled);
Etan Cohena7d32e82015-05-04 18:02:09 -0700586 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700587 loge("setVtSetting: ImsManager null, can not set value.");
Etan Cohena7d32e82015-05-04 18:02:09 -0700588 }
589
Brad Ebinger16417b42017-03-07 13:48:50 -0800590 /**
591 * Change persistent VT enabled setting for slot.
592 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700593 public void setVtSetting(boolean enabled) {
Malcolm Chen212ca652017-09-28 17:28:45 -0700594 SubscriptionManager.setSubscriptionProperty(getSubId(),
595 SubscriptionManager.VT_IMS_ENABLED,
596 booleanToPropertyString(enabled));
Brad Ebinger16417b42017-03-07 13:48:50 -0800597 try {
598 ImsConfig config = getConfigInterface();
599 config.setFeatureValue(ImsConfig.FeatureConstants.FEATURE_TYPE_VIDEO_OVER_LTE,
600 TelephonyManager.NETWORK_TYPE_LTE,
601 enabled ? ImsConfig.FeatureValueConstants.ON
602 : ImsConfig.FeatureValueConstants.OFF,
603 mImsConfigListener);
604
605 if (enabled) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700606 log("setVtSetting(b) : turnOnIms");
Brad Ebinger16417b42017-03-07 13:48:50 -0800607 turnOnIms();
Brad Ebinger479f52c2017-08-28 13:19:22 -0700608 } else if (isVolteEnabledByPlatform()
609 && (!isVolteEnabledByPlatform()
610 || !isEnhanced4gLteModeSettingEnabledByUser())) {
611 log("setVtSetting(b) : imsServiceAllowTurnOff -> turnOffIms");
Brad Ebinger16417b42017-03-07 13:48:50 -0800612 turnOffIms();
613 }
614 } catch (ImsException e) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700615 loge("setVtSetting(b): ", e);
Brad Ebinger16417b42017-03-07 13:48:50 -0800616 }
617 }
618
619 /**
Meng Wang9352c432016-06-08 14:22:20 -0700620 * Returns whether turning off ims is allowed by platform.
621 * The platform property may override the carrier config.
Brad Ebinger16417b42017-03-07 13:48:50 -0800622 *
623 * @deprecated Does not support MSIM devices. Please use
Brad Ebinger479f52c2017-08-28 13:19:22 -0700624 * {@link #isTurnOffImsAllowedByPlatform()} instead.
Meng Wang9352c432016-06-08 14:22:20 -0700625 */
626 private static boolean isTurnOffImsAllowedByPlatform(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700627 ImsManager mgr = ImsManager.getInstance(context,
628 SubscriptionManager.getDefaultVoicePhoneId());
629 if (mgr != null) {
630 return mgr.isTurnOffImsAllowedByPlatform();
Meng Wang9352c432016-06-08 14:22:20 -0700631 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700632 loge("isTurnOffImsAllowedByPlatform: ImsManager null, returning default value.");
633 return true;
Meng Wang9352c432016-06-08 14:22:20 -0700634 }
635
Etan Cohena7d32e82015-05-04 18:02:09 -0700636 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800637 * Returns whether turning off ims is allowed by platform.
638 * The platform property may override the carrier config.
639 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700640 private boolean isTurnOffImsAllowedByPlatform() {
Malcolm Chen18837ff2017-10-25 17:05:41 -0700641 // We first read the per slot value. If doesn't exist, we read the general value. If still
642 // doesn't exist, we use the hardcoded default value.
643 if (SystemProperties.getInt(PROPERTY_DBG_ALLOW_IMS_OFF_OVERRIDE +
644 Integer.toString(mPhoneId), SYSTEM_PROPERTY_NOT_SET) == 1 ||
645 SystemProperties.getInt(
646 PROPERTY_DBG_ALLOW_IMS_OFF_OVERRIDE, SYSTEM_PROPERTY_NOT_SET) == 1) {
Brad Ebinger16417b42017-03-07 13:48:50 -0800647 return true;
648 }
Malcolm Chen18837ff2017-10-25 17:05:41 -0700649
Brad Ebinger479f52c2017-08-28 13:19:22 -0700650 return getBooleanCarrierConfig(
Brad Ebinger16417b42017-03-07 13:48:50 -0800651 CarrierConfigManager.KEY_CARRIER_ALLOW_TURNOFF_IMS_BOOL);
652 }
653
654 /**
Etan Cohena00c9192014-12-23 15:02:29 -0800655 * Returns the user configuration of WFC setting
Brad Ebinger16417b42017-03-07 13:48:50 -0800656 *
657 * @deprecated Does not support MSIM devices. Please use
Brad Ebinger479f52c2017-08-28 13:19:22 -0700658 * {@link #isWfcEnabledByUser()} instead.
Etan Cohena00c9192014-12-23 15:02:29 -0800659 */
660 public static boolean isWfcEnabledByUser(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700661 ImsManager mgr = ImsManager.getInstance(context,
662 SubscriptionManager.getDefaultVoicePhoneId());
663 if (mgr != null) {
664 return mgr.isWfcEnabledByUser();
665 }
666 loge("isWfcEnabledByUser: ImsManager null, returning default value.");
667 return true;
Etan Cohena00c9192014-12-23 15:02:29 -0800668 }
669
670 /**
Malcolm Chen212ca652017-09-28 17:28:45 -0700671 * Returns the user configuration of WFC setting for slot. If not set, it
672 * queries CarrierConfig value as default.
Brad Ebinger16417b42017-03-07 13:48:50 -0800673 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700674 public boolean isWfcEnabledByUser() {
Malcolm Chen212ca652017-09-28 17:28:45 -0700675 int setting = SubscriptionManager.getIntegerSubscriptionProperty(
676 getSubId(), SubscriptionManager.WFC_IMS_ENABLED,
677 SUB_PROPERTY_NOT_INITIALIZED, mContext);
678
679 // SUB_PROPERTY_NOT_INITIALIZED indicates it's never set in sub db.
680 if (setting == SUB_PROPERTY_NOT_INITIALIZED) {
681 return getBooleanCarrierConfig(
682 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ENABLED_BOOL);
683 } else {
manabu, shimoda96aee542017-10-06 15:39:36 +0900684 return setting == ImsConfig.FeatureValueConstants.ON;
Malcolm Chen212ca652017-09-28 17:28:45 -0700685 }
Brad Ebinger16417b42017-03-07 13:48:50 -0800686 }
687
688 /**
689 * Change persistent WFC enabled setting.
690 * @deprecated Does not support MSIM devices. Please use
Brad Ebinger479f52c2017-08-28 13:19:22 -0700691 * {@link #setWfcSetting} instead.
Etan Cohena00c9192014-12-23 15:02:29 -0800692 */
693 public static void setWfcSetting(Context context, boolean enabled) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700694 ImsManager mgr = ImsManager.getInstance(context,
Etan Cohena00c9192014-12-23 15:02:29 -0800695 SubscriptionManager.getDefaultVoicePhoneId());
Brad Ebinger479f52c2017-08-28 13:19:22 -0700696 if (mgr != null) {
697 mgr.setWfcSetting(enabled);
Etan Cohena00c9192014-12-23 15:02:29 -0800698 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700699 loge("setWfcSetting: ImsManager null, can not set value.");
Etan Cohena00c9192014-12-23 15:02:29 -0800700 }
701
702 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800703 * Change persistent WFC enabled setting for slot.
704 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700705 public void setWfcSetting(boolean enabled) {
Malcolm Chen212ca652017-09-28 17:28:45 -0700706 SubscriptionManager.setSubscriptionProperty(getSubId(),
707 SubscriptionManager.WFC_IMS_ENABLED, booleanToPropertyString(enabled));
Brad Ebinger16417b42017-03-07 13:48:50 -0800708
Brad Ebinger479f52c2017-08-28 13:19:22 -0700709 setWfcNonPersistent(enabled, getWfcMode());
Meng Wang51c09072017-03-27 10:47:45 -0700710 }
711
712 /**
713 * Non-persistently change WFC enabled setting and WFC mode for slot
714 *
715 * @param wfcMode The WFC preference if WFC is enabled
716 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700717 public void setWfcNonPersistent(boolean enabled, int wfcMode) {
Meng Wang51c09072017-03-27 10:47:45 -0700718 int imsFeatureValue =
719 enabled ? ImsConfig.FeatureValueConstants.ON : ImsConfig.FeatureValueConstants.OFF;
720 // Force IMS to register over LTE when turning off WFC
721 int imsWfcModeFeatureValue =
722 enabled ? wfcMode : ImsConfig.WfcModeFeatureValueConstants.CELLULAR_PREFERRED;
723
Brad Ebinger16417b42017-03-07 13:48:50 -0800724 try {
725 ImsConfig config = getConfigInterface();
726 config.setFeatureValue(ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_WIFI,
727 TelephonyManager.NETWORK_TYPE_IWLAN,
Meng Wang51c09072017-03-27 10:47:45 -0700728 imsFeatureValue,
Brad Ebinger16417b42017-03-07 13:48:50 -0800729 mImsConfigListener);
730
731 if (enabled) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700732 log("setWfcSetting() : turnOnIms");
Brad Ebinger16417b42017-03-07 13:48:50 -0800733 turnOnIms();
Brad Ebinger479f52c2017-08-28 13:19:22 -0700734 } else if (isTurnOffImsAllowedByPlatform()
735 && (!isVolteEnabledByPlatform()
736 || !isEnhanced4gLteModeSettingEnabledByUser())) {
737 log("setWfcSetting() : imsServiceAllowTurnOff -> turnOffIms");
Brad Ebinger16417b42017-03-07 13:48:50 -0800738 turnOffIms();
739 }
740
Brad Ebinger479f52c2017-08-28 13:19:22 -0700741 setWfcModeInternal(imsWfcModeFeatureValue);
Brad Ebinger16417b42017-03-07 13:48:50 -0800742 } catch (ImsException e) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700743 loge("setWfcSetting(): ", e);
Brad Ebinger16417b42017-03-07 13:48:50 -0800744 }
745 }
746
747 /**
748 * Returns the user configuration of WFC preference setting.
749 *
Malcolm Chen212ca652017-09-28 17:28:45 -0700750 * @deprecated Doesn't support MSIM devices. Use {@link #getWfcMode(boolean roaming)} instead.
Etan Cohena00c9192014-12-23 15:02:29 -0800751 */
752 public static int getWfcMode(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700753 ImsManager mgr = ImsManager.getInstance(context,
754 SubscriptionManager.getDefaultVoicePhoneId());
755 if (mgr != null) {
756 return mgr.getWfcMode();
757 }
758 loge("getWfcMode: ImsManager null, returning default value.");
759 return ImsConfig.WfcModeFeatureValueConstants.WIFI_ONLY;
Etan Cohena00c9192014-12-23 15:02:29 -0800760 }
761
762 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800763 * Returns the user configuration of WFC preference setting
Malcolm Chen212ca652017-09-28 17:28:45 -0700764 * @deprecated. Use {@link #getWfcMode(boolean roaming)} instead.
Brad Ebinger16417b42017-03-07 13:48:50 -0800765 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700766 public int getWfcMode() {
Malcolm Chen212ca652017-09-28 17:28:45 -0700767 return getWfcMode(false);
Brad Ebinger16417b42017-03-07 13:48:50 -0800768 }
769
770 /**
771 * Change persistent WFC preference setting.
772 *
Brad Ebinger479f52c2017-08-28 13:19:22 -0700773 * @deprecated Doesn't support MSIM devices. Use {@link #setWfcMode(int)} instead.
Etan Cohena00c9192014-12-23 15:02:29 -0800774 */
775 public static void setWfcMode(Context context, int wfcMode) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700776 ImsManager mgr = ImsManager.getInstance(context,
777 SubscriptionManager.getDefaultVoicePhoneId());
778 if (mgr != null) {
779 mgr.setWfcMode(wfcMode);
780 }
781 loge("setWfcMode: ImsManager null, can not set value.");
Pavel Zhamaitsiak9e6eca22015-03-16 15:30:53 -0700782 }
783
Meng Wang37477012016-09-20 09:59:56 -0700784 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800785 * Change persistent WFC preference setting for slot.
786 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700787 public void setWfcMode(int wfcMode) {
788 if (DBG) log("setWfcMode(i) - setting=" + wfcMode);
Malcolm Chen212ca652017-09-28 17:28:45 -0700789
790 SubscriptionManager.setSubscriptionProperty(getSubId(),
791 SubscriptionManager.WFC_IMS_MODE, Integer.toString(wfcMode));
Brad Ebinger16417b42017-03-07 13:48:50 -0800792
Brad Ebinger479f52c2017-08-28 13:19:22 -0700793 setWfcModeInternal(wfcMode);
Brad Ebinger16417b42017-03-07 13:48:50 -0800794 }
795
796 /**
Suresh Koleti76491082017-04-21 18:39:50 +0530797 * Changes the WFC mode to its default value for Carriers with non-editable WFC settings.
798 */
799 private void updateDefaultWfcMode() {
800 if (DBG) log("updateDefaultWfcMode");
Brad Ebinger479f52c2017-08-28 13:19:22 -0700801 if (!getBooleanCarrierConfig(CarrierConfigManager.KEY_EDITABLE_WFC_MODE_BOOL)) {
802 setWfcMode(getIntCarrierConfig(
Suresh Koleti76491082017-04-21 18:39:50 +0530803 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_MODE_INT));
804 }
805 }
806
807 /**
Meng Wang37477012016-09-20 09:59:56 -0700808 * Returns the user configuration of WFC preference setting
809 *
810 * @param roaming {@code false} for home network setting, {@code true} for roaming setting
Brad Ebinger16417b42017-03-07 13:48:50 -0800811 *
Brad Ebinger479f52c2017-08-28 13:19:22 -0700812 * @deprecated Doesn't support MSIM devices. Use {@link #getWfcMode(boolean)} instead.
Meng Wang37477012016-09-20 09:59:56 -0700813 */
814 public static int getWfcMode(Context context, boolean roaming) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700815 ImsManager mgr = ImsManager.getInstance(context,
816 SubscriptionManager.getDefaultVoicePhoneId());
817 if (mgr != null) {
818 return mgr.getWfcMode(roaming);
Meng Wang37477012016-09-20 09:59:56 -0700819 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700820 loge("getWfcMode: ImsManager null, returning default value.");
821 return ImsConfig.WfcModeFeatureValueConstants.WIFI_ONLY;
Meng Wang37477012016-09-20 09:59:56 -0700822 }
823
824 /**
Malcolm Chen212ca652017-09-28 17:28:45 -0700825 * Returns the user configuration of WFC preference setting for slot. If not set, it
826 * queries CarrierConfig value as default.
Brad Ebinger16417b42017-03-07 13:48:50 -0800827 *
828 * @param roaming {@code false} for home network setting, {@code true} for roaming setting
829 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700830 public int getWfcMode(boolean roaming) {
Brad Ebinger16417b42017-03-07 13:48:50 -0800831 int setting = 0;
832 if (!roaming) {
Malcolm Chen212ca652017-09-28 17:28:45 -0700833 setting = SubscriptionManager.getIntegerSubscriptionProperty(
834 getSubId(), SubscriptionManager.WFC_IMS_MODE,
835 SUB_PROPERTY_NOT_INITIALIZED, mContext);
836
837 // SUB_PROPERTY_NOT_INITIALIZED indicates it's never set in sub db.
838 if (setting == SUB_PROPERTY_NOT_INITIALIZED) {
839 setting = getIntCarrierConfig(
840 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_MODE_INT);
841 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700842 if (DBG) log("getWfcMode - setting=" + setting);
Brad Ebinger16417b42017-03-07 13:48:50 -0800843 } else {
Malcolm Chen212ca652017-09-28 17:28:45 -0700844 setting = SubscriptionManager.getIntegerSubscriptionProperty(
845 getSubId(), SubscriptionManager.WFC_IMS_ROAMING_MODE,
846 SUB_PROPERTY_NOT_INITIALIZED, mContext);
847
848 // SUB_PROPERTY_NOT_INITIALIZED indicates it's never set in sub db.
849 if (setting == SUB_PROPERTY_NOT_INITIALIZED) {
850 setting = getIntCarrierConfig(
851 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_MODE_INT);
852 }
853
Brad Ebinger479f52c2017-08-28 13:19:22 -0700854 if (DBG) log("getWfcMode (roaming) - setting=" + setting);
Brad Ebinger16417b42017-03-07 13:48:50 -0800855 }
856 return setting;
857 }
858
859 /**
Meng Wang37477012016-09-20 09:59:56 -0700860 * Change persistent WFC preference setting
861 *
862 * @param roaming {@code false} for home network setting, {@code true} for roaming setting
Brad Ebinger16417b42017-03-07 13:48:50 -0800863 *
Brad Ebinger479f52c2017-08-28 13:19:22 -0700864 * @deprecated Doesn't support MSIM devices. Please use {@link #setWfcMode(int, boolean)}
865 * instead.
Meng Wang37477012016-09-20 09:59:56 -0700866 */
867 public static void setWfcMode(Context context, int wfcMode, boolean roaming) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700868 ImsManager mgr = ImsManager.getInstance(context,
869 SubscriptionManager.getDefaultVoicePhoneId());
870 if (mgr != null) {
871 mgr.setWfcMode(wfcMode, roaming);
Meng Wang37477012016-09-20 09:59:56 -0700872 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700873 loge("setWfcMode: ImsManager null, can not set value.");
Meng Wang37477012016-09-20 09:59:56 -0700874 }
875
Brad Ebinger16417b42017-03-07 13:48:50 -0800876 /**
877 * Change persistent WFC preference setting
878 *
879 * @param roaming {@code false} for home network setting, {@code true} for roaming setting
880 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700881 public void setWfcMode(int wfcMode, boolean roaming) {
Brad Ebinger16417b42017-03-07 13:48:50 -0800882 if (!roaming) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700883 if (DBG) log("setWfcMode(i,b) - setting=" + wfcMode);
Malcolm Chen212ca652017-09-28 17:28:45 -0700884 SubscriptionManager.setSubscriptionProperty(getSubId(),
885 SubscriptionManager.WFC_IMS_MODE, Integer.toString(wfcMode));
Brad Ebinger16417b42017-03-07 13:48:50 -0800886 } else {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700887 if (DBG) log("setWfcMode(i,b) (roaming) - setting=" + wfcMode);
Malcolm Chen212ca652017-09-28 17:28:45 -0700888 SubscriptionManager.setSubscriptionProperty(getSubId(),
889 SubscriptionManager.WFC_IMS_ROAMING_MODE, Integer.toString(wfcMode));
Brad Ebinger16417b42017-03-07 13:48:50 -0800890 }
891
Brad Ebinger479f52c2017-08-28 13:19:22 -0700892 TelephonyManager tm = (TelephonyManager)
893 mContext.getSystemService(Context.TELEPHONY_SERVICE);
894 if (roaming == tm.isNetworkRoaming(getSubId())) {
895 setWfcModeInternal(wfcMode);
896 }
897 }
898
899 private int getSubId() {
Brad Ebinger16417b42017-03-07 13:48:50 -0800900 int[] subIds = SubscriptionManager.getSubId(mPhoneId);
901 int subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
902 if (subIds != null && subIds.length >= 1) {
903 subId = subIds[0];
904 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700905 return subId;
Brad Ebinger16417b42017-03-07 13:48:50 -0800906 }
907
Pavel Zhamaitsiak9e6eca22015-03-16 15:30:53 -0700908 private static void setWfcModeInternal(Context context, int wfcMode) {
Etan Cohena00c9192014-12-23 15:02:29 -0800909 final ImsManager imsManager = ImsManager.getInstance(context,
910 SubscriptionManager.getDefaultVoicePhoneId());
911 if (imsManager != null) {
912 final int value = wfcMode;
Pavel Zhamaitsiak47aeacf2016-03-30 18:54:55 -0700913 Thread thread = new Thread(new Runnable() {
Etan Cohena00c9192014-12-23 15:02:29 -0800914 public void run() {
915 try {
916 imsManager.getConfigInterface().setProvisionedValue(
917 ImsConfig.ConfigConstants.VOICE_OVER_WIFI_MODE,
918 value);
919 } catch (ImsException e) {
920 // do nothing
921 }
922 }
923 });
Pavel Zhamaitsiak47aeacf2016-03-30 18:54:55 -0700924 thread.start();
Etan Cohena00c9192014-12-23 15:02:29 -0800925 }
926 }
927
Brad Ebinger479f52c2017-08-28 13:19:22 -0700928 private void setWfcModeInternal(int wfcMode) {
Brad Ebinger16417b42017-03-07 13:48:50 -0800929 final int value = wfcMode;
930 Thread thread = new Thread(() -> {
Malcolm Chen212ca652017-09-28 17:28:45 -0700931 try {
932 getConfigInterface().setProvisionedValue(
933 ImsConfig.ConfigConstants.VOICE_OVER_WIFI_MODE, value);
934 } catch (ImsException e) {
935 // do nothing
936 }
Brad Ebinger16417b42017-03-07 13:48:50 -0800937 });
938 thread.start();
939 }
940
Etan Cohena00c9192014-12-23 15:02:29 -0800941 /**
942 * Returns the user configuration of WFC roaming setting
Brad Ebinger16417b42017-03-07 13:48:50 -0800943 *
944 * @deprecated Does not support MSIM devices. Please use
Brad Ebinger479f52c2017-08-28 13:19:22 -0700945 * {@link #isWfcRoamingEnabledByUser()} instead.
Etan Cohena00c9192014-12-23 15:02:29 -0800946 */
947 public static boolean isWfcRoamingEnabledByUser(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700948 ImsManager mgr = ImsManager.getInstance(context,
949 SubscriptionManager.getDefaultVoicePhoneId());
950 if (mgr != null) {
951 return mgr.isWfcRoamingEnabledByUser();
952 }
953 loge("isWfcRoamingEnabledByUser: ImsManager null, returning default value.");
954 return false;
Etan Cohena00c9192014-12-23 15:02:29 -0800955 }
956
957 /**
Malcolm Chen212ca652017-09-28 17:28:45 -0700958 * Returns the user configuration of WFC roaming setting for slot. If not set, it
959 * queries CarrierConfig value as default.
Brad Ebinger16417b42017-03-07 13:48:50 -0800960 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700961 public boolean isWfcRoamingEnabledByUser() {
Malcolm Chen212ca652017-09-28 17:28:45 -0700962 int setting = SubscriptionManager.getIntegerSubscriptionProperty(
963 getSubId(), SubscriptionManager.WFC_IMS_ROAMING_ENABLED,
964 SUB_PROPERTY_NOT_INITIALIZED, mContext);
965 if (setting == SUB_PROPERTY_NOT_INITIALIZED) {
966 return getBooleanCarrierConfig(
967 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_ENABLED_BOOL);
968 } else {
manabu, shimoda96aee542017-10-06 15:39:36 +0900969 return setting == ImsConfig.FeatureValueConstants.ON;
Malcolm Chen212ca652017-09-28 17:28:45 -0700970 }
Brad Ebinger16417b42017-03-07 13:48:50 -0800971 }
972
973 /**
Etan Cohena00c9192014-12-23 15:02:29 -0800974 * Change persistent WFC roaming enabled setting
975 */
976 public static void setWfcRoamingSetting(Context context, boolean enabled) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700977 ImsManager mgr = ImsManager.getInstance(context,
Etan Cohena00c9192014-12-23 15:02:29 -0800978 SubscriptionManager.getDefaultVoicePhoneId());
Brad Ebinger479f52c2017-08-28 13:19:22 -0700979 if (mgr != null) {
980 mgr.setWfcRoamingSetting(enabled);
Etan Cohena00c9192014-12-23 15:02:29 -0800981 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700982 loge("setWfcRoamingSetting: ImsManager null, value not set.");
Etan Cohena00c9192014-12-23 15:02:29 -0800983 }
984
985 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800986 * Change persistent WFC roaming enabled setting
987 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700988 public void setWfcRoamingSetting(boolean enabled) {
Malcolm Chen212ca652017-09-28 17:28:45 -0700989 SubscriptionManager.setSubscriptionProperty(getSubId(),
990 SubscriptionManager.WFC_IMS_ROAMING_ENABLED, booleanToPropertyString(enabled)
991 );
Brad Ebinger16417b42017-03-07 13:48:50 -0800992
993 setWfcRoamingSettingInternal(enabled);
994 }
995
996 private void setWfcRoamingSettingInternal(boolean enabled) {
997 final int value = enabled
998 ? ImsConfig.FeatureValueConstants.ON
999 : ImsConfig.FeatureValueConstants.OFF;
1000 Thread thread = new Thread(() -> {
Malcolm Chen212ca652017-09-28 17:28:45 -07001001 try {
1002 getConfigInterface().setProvisionedValue(
1003 ImsConfig.ConfigConstants.VOICE_OVER_WIFI_ROAMING, value);
1004 } catch (ImsException e) {
1005 // do nothing
1006 }
Brad Ebinger16417b42017-03-07 13:48:50 -08001007 });
1008 thread.start();
1009 }
1010
1011 /**
Etan Cohena00c9192014-12-23 15:02:29 -08001012 * Returns a platform configuration for WFC which may override the user
1013 * setting. Note: WFC presumes that VoLTE is enabled (these are
1014 * configuration settings which must be done correctly).
Brad Ebinger16417b42017-03-07 13:48:50 -08001015 *
Brad Ebinger479f52c2017-08-28 13:19:22 -07001016 * @deprecated Doesn't work for MSIM devices. Use {@link #isWfcEnabledByPlatform()}
Brad Ebinger16417b42017-03-07 13:48:50 -08001017 * instead.
Etan Cohena00c9192014-12-23 15:02:29 -08001018 */
1019 public static boolean isWfcEnabledByPlatform(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -07001020 ImsManager mgr = ImsManager.getInstance(context,
1021 SubscriptionManager.getDefaultVoicePhoneId());
1022 if (mgr != null) {
1023 return mgr.isWfcEnabledByPlatform();
Etan Cohena00c9192014-12-23 15:02:29 -08001024 }
Brad Ebinger479f52c2017-08-28 13:19:22 -07001025 loge("isWfcEnabledByPlatform: ImsManager null, returning default value.");
1026 return false;
Pavel Zhamaitsiak57911d12015-10-20 14:26:34 -07001027 }
1028
1029 /**
Brad Ebinger16417b42017-03-07 13:48:50 -08001030 * Returns a platform configuration for WFC which may override the user
1031 * setting per slot. Note: WFC presumes that VoLTE is enabled (these are
1032 * configuration settings which must be done correctly).
1033 */
Brad Ebinger479f52c2017-08-28 13:19:22 -07001034 public boolean isWfcEnabledByPlatform() {
Malcolm Chen18837ff2017-10-25 17:05:41 -07001035 // We first read the per slot value. If doesn't exist, we read the general value. If still
1036 // doesn't exist, we use the hardcoded default value.
1037 if (SystemProperties.getInt(PROPERTY_DBG_WFC_AVAIL_OVERRIDE +
1038 Integer.toString(mPhoneId), SYSTEM_PROPERTY_NOT_SET) == 1 ||
1039 SystemProperties.getInt(
1040 PROPERTY_DBG_WFC_AVAIL_OVERRIDE, SYSTEM_PROPERTY_NOT_SET) == 1) {
Brad Ebinger16417b42017-03-07 13:48:50 -08001041 return true;
1042 }
1043
1044 return mContext.getResources().getBoolean(
1045 com.android.internal.R.bool.config_device_wfc_ims_available) &&
Brad Ebinger479f52c2017-08-28 13:19:22 -07001046 getBooleanCarrierConfig(
Brad Ebinger16417b42017-03-07 13:48:50 -08001047 CarrierConfigManager.KEY_CARRIER_WFC_IMS_AVAILABLE_BOOL) &&
Brad Ebinger479f52c2017-08-28 13:19:22 -07001048 isGbaValid();
Etan Cohena00c9192014-12-23 15:02:29 -08001049 }
1050
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001051 /**
Brad Ebinger16417b42017-03-07 13:48:50 -08001052 * If carrier requires that IMS is only available if GBA capable SIM is used,
1053 * then this function checks GBA bit in EF IST.
1054 *
1055 * Format of EF IST is defined in 3GPP TS 31.103 (Section 4.2.7).
1056 */
Brad Ebinger479f52c2017-08-28 13:19:22 -07001057 private boolean isGbaValid() {
1058 if (getBooleanCarrierConfig(
Brad Ebinger16417b42017-03-07 13:48:50 -08001059 CarrierConfigManager.KEY_CARRIER_IMS_GBA_REQUIRED_BOOL)) {
Brad Ebinger479f52c2017-08-28 13:19:22 -07001060 final TelephonyManager telephonyManager = new TelephonyManager(mContext, getSubId());
Brad Ebinger16417b42017-03-07 13:48:50 -08001061 String efIst = telephonyManager.getIsimIst();
1062 if (efIst == null) {
Brad Ebinger479f52c2017-08-28 13:19:22 -07001063 loge("isGbaValid - ISF is NULL");
Brad Ebinger16417b42017-03-07 13:48:50 -08001064 return true;
1065 }
1066 boolean result = efIst != null && efIst.length() > 1 &&
1067 (0x02 & (byte)efIst.charAt(1)) != 0;
Brad Ebinger479f52c2017-08-28 13:19:22 -07001068 if (DBG) log("isGbaValid - GBA capable=" + result + ", ISF=" + efIst);
Brad Ebinger16417b42017-03-07 13:48:50 -08001069 return result;
1070 }
1071 return true;
1072 }
1073
1074 /**
Malcolm Chen18837ff2017-10-25 17:05:41 -07001075 * Will return with config value or throw an ImsException if we receive an error from
1076 * ImsConfig for that value.
1077 */
1078 private boolean getProvisionedBool(ImsConfig config, int item) throws ImsException {
1079 int value = config.getProvisionedValue(item);
1080 if (value == ImsConfig.OperationStatusConstants.UNKNOWN) {
1081 throw new ImsException("getProvisionedBool failed with error for item: " + item,
1082 ImsReasonInfo.CODE_LOCAL_INTERNAL_ERROR);
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -07001083 }
Malcolm Chen18837ff2017-10-25 17:05:41 -07001084 return config.getProvisionedValue(item) == ImsConfig.FeatureValueConstants.ON;
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -07001085 }
1086
1087 /**
Malcolm Chen18837ff2017-10-25 17:05:41 -07001088 * Will return with config value or return false if we receive an error from
1089 * ImsConfig for that value.
Brad Ebingerbe6cb672017-08-25 14:55:00 -07001090 */
Malcolm Chen18837ff2017-10-25 17:05:41 -07001091 private boolean getProvisionedBoolNoException(int item) {
1092 try {
1093 ImsConfig config = getConfigInterface();
1094 return getProvisionedBool(config, item);
1095 } catch (ImsException ex) {
1096 return false;
Brad Ebingerbe6cb672017-08-25 14:55:00 -07001097 }
1098 }
1099
1100 /**
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001101 * Sync carrier config and user settings with ImsConfig.
1102 *
1103 * @param context for the manager object
1104 * @param phoneId phone id
1105 * @param force update
Brad Ebinger16417b42017-03-07 13:48:50 -08001106 *
Brad Ebinger479f52c2017-08-28 13:19:22 -07001107 * @deprecated Doesn't support MSIM devices. Use {@link #updateImsServiceConfig(boolean)}
1108 * instead.
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001109 */
1110 public static void updateImsServiceConfig(Context context, int phoneId, boolean force) {
Brad Ebinger479f52c2017-08-28 13:19:22 -07001111 ImsManager mgr = ImsManager.getInstance(context, phoneId);
1112 if (mgr != null) {
1113 mgr.updateImsServiceConfig(force);
Pavel Zhamaitsiakfc202992016-03-29 18:07:38 -07001114 }
Brad Ebinger479f52c2017-08-28 13:19:22 -07001115 loge("updateImsServiceConfig: ImsManager null, returning without update.");
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001116 }
1117
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -07001118 /**
Brad Ebinger16417b42017-03-07 13:48:50 -08001119 * Sync carrier config and user settings with ImsConfig.
1120 *
Brad Ebinger16417b42017-03-07 13:48:50 -08001121 * @param force update
1122 */
Brad Ebinger479f52c2017-08-28 13:19:22 -07001123 public void updateImsServiceConfig(boolean force) {
Brad Ebinger16417b42017-03-07 13:48:50 -08001124 if (!force) {
Brad Ebinger479f52c2017-08-28 13:19:22 -07001125 TelephonyManager tm = new TelephonyManager(mContext, getSubId());
1126 if (tm.getSimState() != TelephonyManager.SIM_STATE_READY) {
1127 log("updateImsServiceConfig: SIM not ready");
Brad Ebinger16417b42017-03-07 13:48:50 -08001128 // Don't disable IMS if SIM is not ready
1129 return;
1130 }
1131 }
1132
1133 if (!mConfigUpdated || force) {
1134 try {
Brad Ebinger16417b42017-03-07 13:48:50 -08001135 // TODO: Extend ImsConfig API and set all feature values in single function call.
1136
1137 // Note: currently the order of updates is set to produce different order of
1138 // setFeatureValue() function calls from setAdvanced4GMode(). This is done to
1139 // differentiate this code path from vendor code perspective.
1140 boolean isImsUsed = updateVolteFeatureValue();
1141 isImsUsed |= updateWfcFeatureAndProvisionedValues();
1142 isImsUsed |= updateVideoCallFeatureValue();
1143
Brad Ebinger479f52c2017-08-28 13:19:22 -07001144 if (isImsUsed || !isTurnOffImsAllowedByPlatform()) {
Brad Ebinger16417b42017-03-07 13:48:50 -08001145 // Turn on IMS if it is used.
1146 // Also, if turning off is not allowed for current carrier,
1147 // we need to turn IMS on because it might be turned off before
1148 // phone switched to current carrier.
Brad Ebinger479f52c2017-08-28 13:19:22 -07001149 log("updateImsServiceConfig: turnOnIms");
Brad Ebinger16417b42017-03-07 13:48:50 -08001150 turnOnIms();
1151 } else {
1152 // Turn off IMS if it is not used AND turning off is allowed for carrier.
Brad Ebinger479f52c2017-08-28 13:19:22 -07001153 log("updateImsServiceConfig: turnOffIms");
Brad Ebinger16417b42017-03-07 13:48:50 -08001154 turnOffIms();
1155 }
1156
1157 mConfigUpdated = true;
1158 } catch (ImsException e) {
Brad Ebinger479f52c2017-08-28 13:19:22 -07001159 loge("updateImsServiceConfig: ", e);
Brad Ebinger16417b42017-03-07 13:48:50 -08001160 mConfigUpdated = false;
1161 }
1162 }
1163 }
1164
1165 /**
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -07001166 * Update VoLTE config
1167 * @return whether feature is On
1168 * @throws ImsException
1169 */
1170 private boolean updateVolteFeatureValue() throws ImsException {
Brad Ebinger479f52c2017-08-28 13:19:22 -07001171 boolean available = isVolteEnabledByPlatform();
1172 boolean enabled = isEnhanced4gLteModeSettingEnabledByUser();
1173 boolean isNonTty = isNonTtyOrTtyOnVolteEnabled();
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -08001174 boolean isFeatureOn = available && enabled && isNonTty;
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001175
1176 log("updateVolteFeatureValue: available = " + available
1177 + ", enabled = " + enabled
1178 + ", nonTTY = " + isNonTty);
1179
1180 getConfigInterface().setFeatureValue(
1181 ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_LTE,
1182 TelephonyManager.NETWORK_TYPE_LTE,
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -08001183 isFeatureOn ?
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001184 ImsConfig.FeatureValueConstants.ON :
1185 ImsConfig.FeatureValueConstants.OFF,
Pavel Zhamaitsiakf4b90322016-01-26 14:34:09 -08001186 mImsConfigListener);
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -07001187
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -08001188 return isFeatureOn;
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001189 }
1190
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -07001191 /**
Jack Yu643ffe42016-07-08 14:25:46 -07001192 * Update video call over LTE config
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -07001193 * @return whether feature is On
1194 * @throws ImsException
1195 */
1196 private boolean updateVideoCallFeatureValue() throws ImsException {
Brad Ebinger479f52c2017-08-28 13:19:22 -07001197 boolean available = isVtEnabledByPlatform();
1198 boolean enabled = isVtEnabledByUser();
1199 boolean isNonTty = isNonTtyOrTtyOnVolteEnabled();
Amit Mahajan24f7b162016-07-21 16:33:53 -07001200 boolean isDataEnabled = isDataEnabled();
Brad Ebinger479f52c2017-08-28 13:19:22 -07001201 boolean ignoreDataEnabledChanged = getBooleanCarrierConfig(
Jack Yu57781852016-11-16 17:20:38 -08001202 CarrierConfigManager.KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS);
Jack Yu643ffe42016-07-08 14:25:46 -07001203
Jack Yu57781852016-11-16 17:20:38 -08001204 boolean isFeatureOn = available && enabled && isNonTty
1205 && (ignoreDataEnabledChanged || isDataEnabled);
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001206
1207 log("updateVideoCallFeatureValue: available = " + available
1208 + ", enabled = " + enabled
Jack Yu643ffe42016-07-08 14:25:46 -07001209 + ", nonTTY = " + isNonTty
Amit Mahajan24f7b162016-07-21 16:33:53 -07001210 + ", data enabled = " + isDataEnabled);
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001211
1212 getConfigInterface().setFeatureValue(
1213 ImsConfig.FeatureConstants.FEATURE_TYPE_VIDEO_OVER_LTE,
1214 TelephonyManager.NETWORK_TYPE_LTE,
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -08001215 isFeatureOn ?
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001216 ImsConfig.FeatureValueConstants.ON :
1217 ImsConfig.FeatureValueConstants.OFF,
Pavel Zhamaitsiakf4b90322016-01-26 14:34:09 -08001218 mImsConfigListener);
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -07001219
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -08001220 return isFeatureOn;
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001221 }
1222
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -07001223 /**
1224 * Update WFC config
1225 * @return whether feature is On
1226 * @throws ImsException
1227 */
1228 private boolean updateWfcFeatureAndProvisionedValues() throws ImsException {
Brad Ebinger479f52c2017-08-28 13:19:22 -07001229 TelephonyManager tm = new TelephonyManager(mContext, getSubId());
1230 boolean isNetworkRoaming = tm.isNetworkRoaming();
1231 boolean available = isWfcEnabledByPlatform();
1232 boolean enabled = isWfcEnabledByUser();
Suresh Koleti76491082017-04-21 18:39:50 +05301233 updateDefaultWfcMode();
Brad Ebinger479f52c2017-08-28 13:19:22 -07001234 int mode = getWfcMode(isNetworkRoaming);
1235 boolean roaming = isWfcRoamingEnabledByUser();
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -08001236 boolean isFeatureOn = available && enabled;
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001237
1238 log("updateWfcFeatureAndProvisionedValues: available = " + available
1239 + ", enabled = " + enabled
1240 + ", mode = " + mode
1241 + ", roaming = " + roaming);
1242
1243 getConfigInterface().setFeatureValue(
Pavel Zhamaitsiake6f99432015-09-11 10:29:30 -07001244 ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_WIFI,
1245 TelephonyManager.NETWORK_TYPE_IWLAN,
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -08001246 isFeatureOn ?
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001247 ImsConfig.FeatureValueConstants.ON :
1248 ImsConfig.FeatureValueConstants.OFF,
Pavel Zhamaitsiakf4b90322016-01-26 14:34:09 -08001249 mImsConfigListener);
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001250
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -08001251 if (!isFeatureOn) {
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001252 mode = ImsConfig.WfcModeFeatureValueConstants.CELLULAR_PREFERRED;
1253 roaming = false;
1254 }
1255 setWfcModeInternal(mContext, mode);
Brad Ebinger16417b42017-03-07 13:48:50 -08001256 setWfcRoamingSettingInternal(roaming);
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -07001257
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -08001258 return isFeatureOn;
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001259 }
1260
Brad Ebinger16780ff2017-01-26 11:18:21 -08001261 /**
Brad Ebinger479f52c2017-08-28 13:19:22 -07001262 * Do NOT use this directly, instead use {@link #getInstance(Context, int)}.
Brad Ebinger16780ff2017-01-26 11:18:21 -08001263 */
1264 @VisibleForTesting
1265 public ImsManager(Context context, int phoneId) {
Wink Savilleef36ef62014-06-11 08:39:38 -07001266 mContext = context;
Etan Cohenabbd7882014-09-26 22:35:35 -07001267 mPhoneId = phoneId;
Brad Ebinger16780ff2017-01-26 11:18:21 -08001268 mConfigDynamicBind = mContext.getResources().getBoolean(
1269 com.android.internal.R.bool.config_dynamic_bind_ims);
Brad Ebinger16417b42017-03-07 13:48:50 -08001270 mConfigManager = (CarrierConfigManager) context.getSystemService(
1271 Context.CARRIER_CONFIG_SERVICE);
Brad Ebinger16780ff2017-01-26 11:18:21 -08001272 createImsService();
1273 }
1274
1275 /**
Brad Ebinger16780ff2017-01-26 11:18:21 -08001276 * @return Whether or not ImsManager is configured to Dynamically bind or not to support legacy
1277 * devices.
1278 */
1279 public boolean isDynamicBinding() {
1280 return mConfigDynamicBind;
Wink Savilleef36ef62014-06-11 08:39:38 -07001281 }
1282
Etan Cohenf4311122015-02-26 17:47:13 -08001283 /*
Brad Ebingerff097922017-06-19 15:43:08 -07001284 * Returns a flag indicating whether the IMS service is available. If it is not available,
1285 * it will try to connect before reporting failure.
Etan Cohenf4311122015-02-26 17:47:13 -08001286 */
1287 public boolean isServiceAvailable() {
Brad Ebingerff097922017-06-19 15:43:08 -07001288 connectIfServiceIsAvailable();
Brad Ebinger16780ff2017-01-26 11:18:21 -08001289 // mImsServiceProxy will always create an ImsServiceProxy.
1290 return mImsServiceProxy.isBinderAlive();
Etan Cohenf4311122015-02-26 17:47:13 -08001291 }
1292
Suresh Koleticc3139c2017-11-03 18:23:57 +05301293 /*
1294 * Returns a flag indicating whether the IMS service is ready to send requests to lower layers.
1295 */
1296 public boolean isServiceReady() {
1297 connectIfServiceIsAvailable();
1298 return mImsServiceProxy.isBinderReady();
1299 }
1300
Brad Ebingerff097922017-06-19 15:43:08 -07001301 /**
1302 * If the service is available, try to reconnect.
1303 */
1304 public void connectIfServiceIsAvailable() {
1305 if (mImsServiceProxy == null || !mImsServiceProxy.isBinderAlive()) {
1306 createImsService();
1307 }
1308 }
1309
Pavel Zhamaitsiakf4b90322016-01-26 14:34:09 -08001310 public void setImsConfigListener(ImsConfigListener listener) {
1311 mImsConfigListener = listener;
1312 }
1313
Brad Ebingerb10b61e2017-04-18 11:45:26 -07001314
1315 /**
1316 * Adds a callback for status changed events if the binder is already available. If it is not,
1317 * this method will throw an ImsException.
1318 */
Brad Ebinger44fd8af2017-12-14 14:24:02 -08001319 public void addNotifyStatusChangedCallbackIfAvailable(ImsServiceProxy.IFeatureUpdate c)
Brad Ebingerb10b61e2017-04-18 11:45:26 -07001320 throws ImsException {
1321 if (!mImsServiceProxy.isBinderAlive()) {
1322 throw new ImsException("Binder is not active!",
1323 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1324 }
Brad Ebinger16780ff2017-01-26 11:18:21 -08001325 if (c != null) {
1326 mStatusCallbacks.add(c);
1327 }
1328 }
1329
Brad Ebinger44fd8af2017-12-14 14:24:02 -08001330 public void removeNotifyStatusChangedCallback(ImsServiceProxy.IFeatureUpdate c) {
1331 if (c != null) {
1332 mStatusCallbacks.remove(c);
1333 } else {
1334 Log.w(TAG, "removeNotifyStatusChangedCallback: callback is null!");
1335 }
1336 }
1337
Wink Savilleef36ef62014-06-11 08:39:38 -07001338 /**
1339 * Opens the IMS service for making calls and/or receiving generic IMS calls.
1340 * The caller may make subsquent calls through {@link #makeCall}.
1341 * The IMS service will register the device to the operator's network with the credentials
1342 * (from ISIM) periodically in order to receive calls from the operator's network.
1343 * When the IMS service receives a new call, it will send out an intent with
1344 * the provided action string.
1345 * The intent contains a call ID extra {@link getCallId} and it can be used to take a call.
1346 *
1347 * @param serviceClass a service class specified in {@link ImsServiceClass}
1348 * For VoLTE service, it MUST be a {@link ImsServiceClass#MMTEL}.
1349 * @param incomingCallPendingIntent When an incoming call is received,
1350 * the IMS service will call {@link PendingIntent#send(Context, int, Intent)} to
1351 * send back the intent to the caller with {@link #INCOMING_CALL_RESULT_CODE}
1352 * as the result code and the intent to fill in the call ID; It cannot be null
1353 * @param listener To listen to IMS registration events; It cannot be null
1354 * @return identifier (greater than 0) for the specified service
1355 * @throws NullPointerException if {@code incomingCallPendingIntent}
1356 * or {@code listener} is null
1357 * @throws ImsException if calling the IMS service results in an error
1358 * @see #getCallId
Brad Ebinger16780ff2017-01-26 11:18:21 -08001359 * @see #getImsSessionId
Wink Savilleef36ef62014-06-11 08:39:38 -07001360 */
1361 public int open(int serviceClass, PendingIntent incomingCallPendingIntent,
1362 ImsConnectionStateListener listener) throws ImsException {
1363 checkAndThrowExceptionIfServiceUnavailable();
1364
1365 if (incomingCallPendingIntent == null) {
1366 throw new NullPointerException("incomingCallPendingIntent can't be null");
1367 }
1368
1369 if (listener == null) {
1370 throw new NullPointerException("listener can't be null");
1371 }
1372
1373 int result = 0;
1374
1375 try {
Brad Ebinger57b11892017-06-13 16:21:35 -07001376 // Register a stub implementation of the ImsRegistrationListener. There is the
1377 // possibility that if we use the real implementation of the ImsRegistrationListener,
1378 // it will be added twice.
1379 // TODO: Remove ImsRegistrationListener from startSession API (b/62588776)
Brad Ebinger16780ff2017-01-26 11:18:21 -08001380 result = mImsServiceProxy.startSession(incomingCallPendingIntent,
Brad Ebinger57b11892017-06-13 16:21:35 -07001381 new ImsRegistrationListenerBase());
1382 addRegistrationListener(listener);
1383 log("open: Session started and registration listener added.");
Wink Savilleef36ef62014-06-11 08:39:38 -07001384 } catch (RemoteException e) {
1385 throw new ImsException("open()", e,
1386 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1387 }
1388
1389 if (result <= 0) {
1390 // If the return value is a minus value,
1391 // it means that an error occurred in the service.
1392 // So, it needs to convert to the reason code specified in ImsReasonInfo.
1393 throw new ImsException("open()", (result * (-1)));
1394 }
1395
1396 return result;
1397 }
1398
1399 /**
Pavel Zhamaitsiakce410172016-04-15 10:55:56 -07001400 * Adds registration listener to the IMS service.
1401 *
1402 * @param serviceClass a service class specified in {@link ImsServiceClass}
1403 * For VoLTE service, it MUST be a {@link ImsServiceClass#MMTEL}.
1404 * @param listener To listen to IMS registration events; It cannot be null
1405 * @throws NullPointerException if {@code listener} is null
1406 * @throws ImsException if calling the IMS service results in an error
Brad Ebinger9a0280c2017-06-01 15:58:48 -07001407 *
1408 * @deprecated Use {@link #addRegistrationListener(ImsConnectionStateListener)} instead.
Pavel Zhamaitsiakce410172016-04-15 10:55:56 -07001409 */
1410 public void addRegistrationListener(int serviceClass, ImsConnectionStateListener listener)
1411 throws ImsException {
Brad Ebinger9a0280c2017-06-01 15:58:48 -07001412 addRegistrationListener(listener);
1413 }
1414
1415 /**
1416 * Adds registration listener to the IMS service.
1417 *
1418 * @param listener To listen to IMS registration events; It cannot be null
1419 * @throws NullPointerException if {@code listener} is null
1420 * @throws ImsException if calling the IMS service results in an error
1421 */
Brad Ebinger44fd8af2017-12-14 14:24:02 -08001422 public void addRegistrationListener(ImsConnectionStateListener listener) throws ImsException {
Pavel Zhamaitsiakce410172016-04-15 10:55:56 -07001423 if (listener == null) {
1424 throw new NullPointerException("listener can't be null");
1425 }
Brad Ebinger57b11892017-06-13 16:21:35 -07001426 // We only want this Proxy registered once.
Brad Ebinger9a0280c2017-06-01 15:58:48 -07001427 synchronized (mHasRegisteredLock) {
1428 if (!mHasRegisteredForProxy) {
1429 try {
Brad Ebinger57b11892017-06-13 16:21:35 -07001430 checkAndThrowExceptionIfServiceUnavailable();
Brad Ebinger44fd8af2017-12-14 14:24:02 -08001431 // TODO: Remove once new MmTelFeature is merged in
1432 mImsServiceProxy.addRegistrationListener(mImsRegistrationListenerProxy);
Brad Ebinger3418c132018-01-18 12:03:33 -08001433 IImsRegistration regBinder = mImsServiceProxy.getRegistration();
1434 if (regBinder != null) {
1435 regBinder.addRegistrationCallback(mRegistrationCallback);
1436 }
Brad Ebinger44fd8af2017-12-14 14:24:02 -08001437 log("Registration Callback/Listener registered.");
Brad Ebinger9a0280c2017-06-01 15:58:48 -07001438 // Only record if there isn't a RemoteException.
1439 mHasRegisteredForProxy = true;
1440 } catch (RemoteException e) {
1441 throw new ImsException("addRegistrationListener()", e,
1442 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1443 }
1444 }
1445 }
1446 synchronized (mRegistrationListeners) {
Brad Ebinger57b11892017-06-13 16:21:35 -07001447 log("Local registration listener added: " + listener);
Brad Ebinger9a0280c2017-06-01 15:58:48 -07001448 mRegistrationListeners.add(listener);
Pavel Zhamaitsiakce410172016-04-15 10:55:56 -07001449 }
1450 }
1451
1452 /**
Brad Ebinger16780ff2017-01-26 11:18:21 -08001453 * Removes the registration listener from the IMS service.
1454 *
Brad Ebinger16780ff2017-01-26 11:18:21 -08001455 * @param listener Previously registered listener that will be removed. Can not be null.
1456 * @throws NullPointerException if {@code listener} is null
1457 * @throws ImsException if calling the IMS service results in an error
1458 * instead.
1459 */
Brad Ebingerb5f30c72017-02-17 14:54:31 -08001460 public void removeRegistrationListener(ImsConnectionStateListener listener)
Brad Ebinger16780ff2017-01-26 11:18:21 -08001461 throws ImsException {
Brad Ebinger16780ff2017-01-26 11:18:21 -08001462 if (listener == null) {
1463 throw new NullPointerException("listener can't be null");
1464 }
1465
Brad Ebinger9a0280c2017-06-01 15:58:48 -07001466 synchronized (mRegistrationListeners) {
Brad Ebinger57b11892017-06-13 16:21:35 -07001467 log("Local registration listener removed: " + listener);
Brad Ebinger9a0280c2017-06-01 15:58:48 -07001468 mRegistrationListeners.remove(listener);
Brad Ebinger16780ff2017-01-26 11:18:21 -08001469 }
1470 }
1471
1472 /**
Wink Savilleef36ef62014-06-11 08:39:38 -07001473 * Closes the specified service ({@link ImsServiceClass}) not to make/receive calls.
1474 * All the resources that were allocated to the service are also released.
1475 *
Brad Ebinger16780ff2017-01-26 11:18:21 -08001476 * @param sessionId a session id to be closed which is obtained from {@link ImsManager#open}
Wink Savilleef36ef62014-06-11 08:39:38 -07001477 * @throws ImsException if calling the IMS service results in an error
1478 */
Brad Ebinger16780ff2017-01-26 11:18:21 -08001479 public void close(int sessionId) throws ImsException {
Wink Savilleef36ef62014-06-11 08:39:38 -07001480 checkAndThrowExceptionIfServiceUnavailable();
1481
1482 try {
Brad Ebinger16780ff2017-01-26 11:18:21 -08001483 mImsServiceProxy.endSession(sessionId);
Wink Savilleef36ef62014-06-11 08:39:38 -07001484 } catch (RemoteException e) {
1485 throw new ImsException("close()", e,
1486 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1487 } finally {
1488 mUt = null;
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -05001489 mConfig = null;
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -07001490 mEcbm = null;
Tyler Gunn4d128b62016-04-13 15:44:38 -07001491 mMultiEndpoint = null;
Wink Savilleef36ef62014-06-11 08:39:38 -07001492 }
1493 }
1494
1495 /**
1496 * Gets the configuration interface to provision / withdraw the supplementary service settings.
1497 *
Wink Savilleef36ef62014-06-11 08:39:38 -07001498 * @return the Ut interface instance
1499 * @throws ImsException if getting the Ut interface results in an error
1500 */
Brad Ebingerb5f30c72017-02-17 14:54:31 -08001501 public ImsUtInterface getSupplementaryServiceConfiguration()
Wink Savilleef36ef62014-06-11 08:39:38 -07001502 throws ImsException {
Brad Ebinger16780ff2017-01-26 11:18:21 -08001503 // FIXME: manage the multiple Ut interfaces based on the session id
Brad Ebinger138b4a62017-06-20 16:29:50 -07001504 if (mUt != null && mUt.isBinderAlive()) {
1505 return mUt;
Wink Savilleef36ef62014-06-11 08:39:38 -07001506 }
1507
Brad Ebinger138b4a62017-06-20 16:29:50 -07001508 checkAndThrowExceptionIfServiceUnavailable();
1509 try {
1510 IImsUt iUt = mImsServiceProxy.getUtInterface();
1511
1512 if (iUt == null) {
1513 throw new ImsException("getSupplementaryServiceConfiguration()",
1514 ImsReasonInfo.CODE_UT_NOT_SUPPORTED);
1515 }
1516
1517 mUt = new ImsUt(iUt);
1518 } catch (RemoteException e) {
1519 throw new ImsException("getSupplementaryServiceConfiguration()", e,
1520 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1521 }
Wink Savilleef36ef62014-06-11 08:39:38 -07001522 return mUt;
1523 }
1524
1525 /**
1526 * Checks if the IMS service has successfully registered to the IMS network
1527 * with the specified service & call type.
1528 *
Wink Savilleef36ef62014-06-11 08:39:38 -07001529 * @param serviceType a service type that is specified in {@link ImsCallProfile}
1530 * {@link ImsCallProfile#SERVICE_TYPE_NORMAL}
1531 * {@link ImsCallProfile#SERVICE_TYPE_EMERGENCY}
1532 * @param callType a call type that is specified in {@link ImsCallProfile}
1533 * {@link ImsCallProfile#CALL_TYPE_VOICE_N_VIDEO}
1534 * {@link ImsCallProfile#CALL_TYPE_VOICE}
1535 * {@link ImsCallProfile#CALL_TYPE_VT}
1536 * {@link ImsCallProfile#CALL_TYPE_VS}
1537 * @return true if the specified service id is connected to the IMS network;
1538 * false otherwise
1539 * @throws ImsException if calling the IMS service results in an error
1540 */
Brad Ebingerb5f30c72017-02-17 14:54:31 -08001541 public boolean isConnected(int serviceType, int callType)
Wink Savilleef36ef62014-06-11 08:39:38 -07001542 throws ImsException {
1543 checkAndThrowExceptionIfServiceUnavailable();
1544
1545 try {
Brad Ebingerb5f30c72017-02-17 14:54:31 -08001546 return mImsServiceProxy.isConnected(serviceType, callType);
Wink Savilleef36ef62014-06-11 08:39:38 -07001547 } catch (RemoteException e) {
1548 throw new ImsException("isServiceConnected()", e,
1549 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1550 }
1551 }
1552
1553 /**
1554 * Checks if the specified IMS service is opend.
1555 *
Wink Savilleef36ef62014-06-11 08:39:38 -07001556 * @return true if the specified service id is opened; false otherwise
1557 * @throws ImsException if calling the IMS service results in an error
1558 */
Brad Ebingerb5f30c72017-02-17 14:54:31 -08001559 public boolean isOpened() throws ImsException {
Wink Savilleef36ef62014-06-11 08:39:38 -07001560 checkAndThrowExceptionIfServiceUnavailable();
1561
1562 try {
Brad Ebingerb5f30c72017-02-17 14:54:31 -08001563 return mImsServiceProxy.isOpened();
Wink Savilleef36ef62014-06-11 08:39:38 -07001564 } catch (RemoteException e) {
1565 throw new ImsException("isOpened()", e,
1566 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1567 }
1568 }
1569
1570 /**
1571 * Creates a {@link ImsCallProfile} from the service capabilities & IMS registration state.
1572 *
Brad Ebinger16780ff2017-01-26 11:18:21 -08001573 * @param sessionId a session id which is obtained from {@link ImsManager#open}
Wink Savilleef36ef62014-06-11 08:39:38 -07001574 * @param serviceType a service type that is specified in {@link ImsCallProfile}
1575 * {@link ImsCallProfile#SERVICE_TYPE_NONE}
1576 * {@link ImsCallProfile#SERVICE_TYPE_NORMAL}
1577 * {@link ImsCallProfile#SERVICE_TYPE_EMERGENCY}
1578 * @param callType a call type that is specified in {@link ImsCallProfile}
1579 * {@link ImsCallProfile#CALL_TYPE_VOICE}
1580 * {@link ImsCallProfile#CALL_TYPE_VT}
1581 * {@link ImsCallProfile#CALL_TYPE_VT_TX}
1582 * {@link ImsCallProfile#CALL_TYPE_VT_RX}
1583 * {@link ImsCallProfile#CALL_TYPE_VT_NODIR}
1584 * {@link ImsCallProfile#CALL_TYPE_VS}
1585 * {@link ImsCallProfile#CALL_TYPE_VS_TX}
1586 * {@link ImsCallProfile#CALL_TYPE_VS_RX}
1587 * @return a {@link ImsCallProfile} object
1588 * @throws ImsException if calling the IMS service results in an error
1589 */
Brad Ebingerb5f30c72017-02-17 14:54:31 -08001590 public ImsCallProfile createCallProfile(int sessionId, int serviceType, int callType)
1591 throws ImsException {
Wink Savilleef36ef62014-06-11 08:39:38 -07001592 checkAndThrowExceptionIfServiceUnavailable();
1593
1594 try {
Brad Ebinger16780ff2017-01-26 11:18:21 -08001595 return mImsServiceProxy.createCallProfile(sessionId, serviceType, callType);
Wink Savilleef36ef62014-06-11 08:39:38 -07001596 } catch (RemoteException e) {
1597 throw new ImsException("createCallProfile()", e,
1598 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1599 }
1600 }
1601
1602 /**
1603 * Creates a {@link ImsCall} to make a call.
1604 *
Brad Ebinger16780ff2017-01-26 11:18:21 -08001605 * @param sessionId a session id which is obtained from {@link ImsManager#open}
Wink Savilleef36ef62014-06-11 08:39:38 -07001606 * @param profile a call profile to make the call
1607 * (it contains service type, call type, media information, etc.)
1608 * @param participants participants to invite the conference call
1609 * @param listener listen to the call events from {@link ImsCall}
1610 * @return a {@link ImsCall} object
1611 * @throws ImsException if calling the IMS service results in an error
1612 */
Brad Ebinger16780ff2017-01-26 11:18:21 -08001613 public ImsCall makeCall(int sessionId, ImsCallProfile profile, String[] callees,
Wink Savilleef36ef62014-06-11 08:39:38 -07001614 ImsCall.Listener listener) throws ImsException {
1615 if (DBG) {
Brad Ebinger16780ff2017-01-26 11:18:21 -08001616 log("makeCall :: sessionId=" + sessionId
fionaxu7b3107c2016-07-06 14:04:06 -07001617 + ", profile=" + profile);
Wink Savilleef36ef62014-06-11 08:39:38 -07001618 }
1619
1620 checkAndThrowExceptionIfServiceUnavailable();
1621
1622 ImsCall call = new ImsCall(mContext, profile);
1623
1624 call.setListener(listener);
Brad Ebinger16780ff2017-01-26 11:18:21 -08001625 ImsCallSession session = createCallSession(sessionId, profile);
Wink Savilleef36ef62014-06-11 08:39:38 -07001626
1627 if ((callees != null) && (callees.length == 1)) {
1628 call.start(session, callees[0]);
1629 } else {
1630 call.start(session, callees);
1631 }
1632
1633 return call;
1634 }
1635
1636 /**
1637 * Creates a {@link ImsCall} to take an incoming call.
1638 *
Brad Ebinger16780ff2017-01-26 11:18:21 -08001639 * @param sessionId a session id which is obtained from {@link ImsManager#open}
Wink Savilleef36ef62014-06-11 08:39:38 -07001640 * @param incomingCallIntent the incoming call broadcast intent
1641 * @param listener to listen to the call events from {@link ImsCall}
1642 * @return a {@link ImsCall} object
1643 * @throws ImsException if calling the IMS service results in an error
1644 */
Brad Ebinger16780ff2017-01-26 11:18:21 -08001645 public ImsCall takeCall(int sessionId, Intent incomingCallIntent,
Wink Savilleef36ef62014-06-11 08:39:38 -07001646 ImsCall.Listener listener) throws ImsException {
1647 if (DBG) {
Brad Ebinger16780ff2017-01-26 11:18:21 -08001648 log("takeCall :: sessionId=" + sessionId
Wink Savilleef36ef62014-06-11 08:39:38 -07001649 + ", incomingCall=" + incomingCallIntent);
1650 }
1651
1652 checkAndThrowExceptionIfServiceUnavailable();
1653
1654 if (incomingCallIntent == null) {
1655 throw new ImsException("Can't retrieve session with null intent",
1656 ImsReasonInfo.CODE_LOCAL_ILLEGAL_ARGUMENT);
1657 }
1658
Brad Ebinger16780ff2017-01-26 11:18:21 -08001659 int incomingServiceId = getImsSessionId(incomingCallIntent);
Wink Savilleef36ef62014-06-11 08:39:38 -07001660
Brad Ebinger16780ff2017-01-26 11:18:21 -08001661 if (sessionId != incomingServiceId) {
Wink Savilleef36ef62014-06-11 08:39:38 -07001662 throw new ImsException("Service id is mismatched in the incoming call intent",
1663 ImsReasonInfo.CODE_LOCAL_ILLEGAL_ARGUMENT);
1664 }
1665
1666 String callId = getCallId(incomingCallIntent);
1667
1668 if (callId == null) {
1669 throw new ImsException("Call ID missing in the incoming call intent",
1670 ImsReasonInfo.CODE_LOCAL_ILLEGAL_ARGUMENT);
1671 }
1672
1673 try {
Brad Ebinger16780ff2017-01-26 11:18:21 -08001674 IImsCallSession session = mImsServiceProxy.getPendingCallSession(sessionId, callId);
Wink Savilleef36ef62014-06-11 08:39:38 -07001675
1676 if (session == null) {
1677 throw new ImsException("No pending session for the call",
1678 ImsReasonInfo.CODE_LOCAL_NO_PENDING_CALL);
1679 }
1680
1681 ImsCall call = new ImsCall(mContext, session.getCallProfile());
1682
1683 call.attachSession(new ImsCallSession(session));
1684 call.setListener(listener);
1685
1686 return call;
1687 } catch (Throwable t) {
1688 throw new ImsException("takeCall()", t, ImsReasonInfo.CODE_UNSPECIFIED);
1689 }
1690 }
1691
1692 /**
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -05001693 * Gets the config interface to get/set service/capability parameters.
1694 *
1695 * @return the ImsConfig instance.
1696 * @throws ImsException if getting the setting interface results in an error.
1697 */
1698 public ImsConfig getConfigInterface() throws ImsException {
Brad Ebinger138b4a62017-06-20 16:29:50 -07001699 if (mConfig != null && mConfig.isBinderAlive()) {
1700 return mConfig;
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -05001701 }
Brad Ebinger138b4a62017-06-20 16:29:50 -07001702
1703 checkAndThrowExceptionIfServiceUnavailable();
1704 try {
1705 IImsConfig config = mImsServiceProxy.getConfigInterface();
1706 if (config == null) {
1707 throw new ImsException("getConfigInterface()",
1708 ImsReasonInfo.CODE_LOCAL_SERVICE_UNAVAILABLE);
1709 }
1710 mConfig = new ImsConfig(config, mContext);
1711 } catch (RemoteException e) {
1712 throw new ImsException("getConfigInterface()", e,
1713 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1714 }
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -05001715 return mConfig;
1716 }
1717
Hall Liue511a202017-08-17 15:49:58 -07001718 /**
1719 * Set the TTY mode. This is the actual tty mode (varies depending on peripheral status)
1720 */
1721 public void setTtyMode(int ttyMode) throws ImsException {
Brad Ebinger479f52c2017-08-28 13:19:22 -07001722 if (!getBooleanCarrierConfig(
Hall Liue511a202017-08-17 15:49:58 -07001723 CarrierConfigManager.KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL)) {
1724 setAdvanced4GMode((ttyMode == TelecomManager.TTY_MODE_OFF) &&
Brad Ebinger479f52c2017-08-28 13:19:22 -07001725 isEnhanced4gLteModeSettingEnabledByUser());
Hall Liue511a202017-08-17 15:49:58 -07001726 }
1727 }
1728
1729 /**
1730 * Sets the UI TTY mode. This is the preferred TTY mode that the user sets in the call
1731 * settings screen.
1732 */
Brad Ebingerb5f30c72017-02-17 14:54:31 -08001733 public void setUiTTYMode(Context context, int uiTtyMode, Message onComplete)
Shriram Ganeshc403b7b2014-08-14 14:18:57 +05301734 throws ImsException {
1735
Etan Cohen82f78122014-12-15 10:10:14 -08001736 checkAndThrowExceptionIfServiceUnavailable();
Shriram Ganeshc403b7b2014-08-14 14:18:57 +05301737
Etan Cohen82f78122014-12-15 10:10:14 -08001738 try {
Brad Ebingerb5f30c72017-02-17 14:54:31 -08001739 mImsServiceProxy.setUiTTYMode(uiTtyMode, onComplete);
Etan Cohen82f78122014-12-15 10:10:14 -08001740 } catch (RemoteException e) {
1741 throw new ImsException("setTTYMode()", e,
1742 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1743 }
Shriram Ganeshc403b7b2014-08-14 14:18:57 +05301744 }
1745
Naveen Kalla525c3a22017-02-06 14:46:42 -08001746 private ImsReasonInfo makeACopy(ImsReasonInfo imsReasonInfo) {
1747 Parcel p = Parcel.obtain();
1748 imsReasonInfo.writeToParcel(p, 0);
1749 p.setDataPosition(0);
1750 ImsReasonInfo clonedReasonInfo = ImsReasonInfo.CREATOR.createFromParcel(p);
1751 p.recycle();
1752 return clonedReasonInfo;
1753 }
1754
1755 /**
1756 * Get Recent IMS Disconnect Reasons.
1757 *
1758 * @return ArrayList of ImsReasonInfo objects. MAX size of the arraylist
1759 * is MAX_RECENT_DISCONNECT_REASONS. The objects are in the
1760 * chronological order.
1761 */
1762 public ArrayList<ImsReasonInfo> getRecentImsDisconnectReasons() {
1763 ArrayList<ImsReasonInfo> disconnectReasons = new ArrayList<>();
1764
1765 for (ImsReasonInfo reason : mRecentDisconnectReasons) {
1766 disconnectReasons.add(makeACopy(reason));
1767 }
1768 return disconnectReasons;
1769 }
Brad Ebinger16417b42017-03-07 13:48:50 -08001770
Brad Ebinger16780ff2017-01-26 11:18:21 -08001771 public int getImsServiceStatus() throws ImsException {
Brad Ebinger16780ff2017-01-26 11:18:21 -08001772 return mImsServiceProxy.getFeatureStatus();
1773 }
Naveen Kalla525c3a22017-02-06 14:46:42 -08001774
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -05001775 /**
Junda Liue7663c02015-06-23 11:16:26 -07001776 * Get the boolean config from carrier config manager.
1777 *
Brad Ebinger16417b42017-03-07 13:48:50 -08001778 * @param key config key defined in CarrierConfigManager
1779 * @return boolean value of corresponding key.
1780 */
Brad Ebinger479f52c2017-08-28 13:19:22 -07001781 private boolean getBooleanCarrierConfig(String key) {
Brad Ebinger16417b42017-03-07 13:48:50 -08001782 int[] subIds = SubscriptionManager.getSubId(mPhoneId);
1783 int subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1784 if (subIds != null && subIds.length >= 1) {
1785 subId = subIds[0];
1786 }
1787 PersistableBundle b = null;
1788 if (mConfigManager != null) {
1789 // If an invalid subId is used, this bundle will contain default values.
1790 b = mConfigManager.getConfigForSubId(subId);
1791 }
1792 if (b != null) {
1793 return b.getBoolean(key);
1794 } else {
1795 // Return static default defined in CarrierConfigManager.
1796 return CarrierConfigManager.getDefaultConfig().getBoolean(key);
1797 }
1798 }
1799
1800 /**
fionaxu5803ef02016-03-08 11:48:48 -08001801 * Get the int config from carrier config manager.
1802 *
Brad Ebinger16417b42017-03-07 13:48:50 -08001803 * @param key config key defined in CarrierConfigManager
1804 * @return integer value of corresponding key.
1805 */
Brad Ebinger479f52c2017-08-28 13:19:22 -07001806 private int getIntCarrierConfig(String key) {
Brad Ebinger16417b42017-03-07 13:48:50 -08001807 int[] subIds = SubscriptionManager.getSubId(mPhoneId);
1808 int subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1809 if (subIds != null && subIds.length >= 1) {
1810 subId = subIds[0];
1811 }
1812 PersistableBundle b = null;
1813 if (mConfigManager != null) {
1814 // If an invalid subId is used, this bundle will contain default values.
1815 b = mConfigManager.getConfigForSubId(subId);
1816 }
1817 if (b != null) {
1818 return b.getInt(key);
1819 } else {
1820 // Return static default defined in CarrierConfigManager.
1821 return CarrierConfigManager.getDefaultConfig().getInt(key);
1822 }
1823 }
1824
1825 /**
Wink Savilleef36ef62014-06-11 08:39:38 -07001826 * Gets the call ID from the specified incoming call broadcast intent.
1827 *
1828 * @param incomingCallIntent the incoming call broadcast intent
1829 * @return the call ID or null if the intent does not contain it
1830 */
1831 private static String getCallId(Intent incomingCallIntent) {
1832 if (incomingCallIntent == null) {
1833 return null;
1834 }
1835
1836 return incomingCallIntent.getStringExtra(EXTRA_CALL_ID);
1837 }
1838
1839 /**
1840 * Gets the service type from the specified incoming call broadcast intent.
1841 *
1842 * @param incomingCallIntent the incoming call broadcast intent
Brad Ebinger16780ff2017-01-26 11:18:21 -08001843 * @return the session identifier or -1 if the intent does not contain it
Wink Savilleef36ef62014-06-11 08:39:38 -07001844 */
Brad Ebinger16780ff2017-01-26 11:18:21 -08001845 private static int getImsSessionId(Intent incomingCallIntent) {
Wink Savilleef36ef62014-06-11 08:39:38 -07001846 if (incomingCallIntent == null) {
1847 return (-1);
1848 }
1849
1850 return incomingCallIntent.getIntExtra(EXTRA_SERVICE_ID, -1);
1851 }
1852
1853 /**
Brad Ebingerb10b61e2017-04-18 11:45:26 -07001854 * Checks to see if the ImsService Binder is connected. If it is not, we try to create the
1855 * connection again.
Wink Savilleef36ef62014-06-11 08:39:38 -07001856 */
1857 private void checkAndThrowExceptionIfServiceUnavailable()
1858 throws ImsException {
Brad Ebinger16780ff2017-01-26 11:18:21 -08001859 if (mImsServiceProxy == null || !mImsServiceProxy.isBinderAlive()) {
1860 createImsService();
Wink Savilleef36ef62014-06-11 08:39:38 -07001861
Brad Ebinger16780ff2017-01-26 11:18:21 -08001862 if (mImsServiceProxy == null) {
Wink Savilleef36ef62014-06-11 08:39:38 -07001863 throw new ImsException("Service is unavailable",
1864 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1865 }
1866 }
1867 }
1868
Brad Ebinger16780ff2017-01-26 11:18:21 -08001869 /**
1870 * Binds the IMS service to make/receive the call. Supports two methods of exposing an
1871 * ImsService:
1872 * 1) com.android.ims.ImsService implementation in ServiceManager (deprecated).
1873 * 2) android.telephony.ims.ImsService implementation through ImsResolver.
1874 */
1875 private void createImsService() {
1876 if (!mConfigDynamicBind) {
Brad Ebinger44fd8af2017-12-14 14:24:02 -08001877 // Deprecated method of binding
Brad Ebinger16780ff2017-01-26 11:18:21 -08001878 Rlog.i(TAG, "Creating ImsService using ServiceManager");
Brad Ebinger3418c132018-01-18 12:03:33 -08001879 mImsServiceProxy = ImsServiceProxyCompat.create(mContext, mPhoneId, mDeathRecipient);
Brad Ebinger16780ff2017-01-26 11:18:21 -08001880 } else {
1881 Rlog.i(TAG, "Creating ImsService using ImsResolver");
Brad Ebinger44fd8af2017-12-14 14:24:02 -08001882 mImsServiceProxy = ImsServiceProxy.create(mContext, mPhoneId);
Brad Ebinger16780ff2017-01-26 11:18:21 -08001883 }
Brad Ebinger44fd8af2017-12-14 14:24:02 -08001884 // Forwarding interface to tell mStatusCallbacks that the Proxy is unavailable.
1885 mImsServiceProxy.setStatusCallback(new ImsServiceProxy.IFeatureUpdate() {
1886 @Override
1887 public void notifyStateChanged() {
1888 mStatusCallbacks.forEach(ImsServiceProxy.IFeatureUpdate::notifyStateChanged);
1889 }
1890
1891 @Override
1892 public void notifyUnavailable() {
1893 mStatusCallbacks.forEach(ImsServiceProxy.IFeatureUpdate::notifyUnavailable);
1894 }
1895 });
Brad Ebinger9a0280c2017-06-01 15:58:48 -07001896 // We have created a new ImsService connection, signal for re-registration
1897 synchronized (mHasRegisteredLock) {
1898 mHasRegisteredForProxy = false;
1899 }
Etan Cohend7727462014-07-12 14:54:10 -07001900 }
1901
Wink Savilleef36ef62014-06-11 08:39:38 -07001902 /**
1903 * Creates a {@link ImsCallSession} with the specified call profile.
1904 * Use other methods, if applicable, instead of interacting with
1905 * {@link ImsCallSession} directly.
1906 *
1907 * @param serviceId a service id which is obtained from {@link ImsManager#open}
1908 * @param profile a call profile to make the call
1909 */
1910 private ImsCallSession createCallSession(int serviceId,
1911 ImsCallProfile profile) throws ImsException {
1912 try {
Brad Ebingerb10b61e2017-04-18 11:45:26 -07001913 // Throws an exception if the ImsService Feature is not ready to accept commands.
Brad Ebinger16780ff2017-01-26 11:18:21 -08001914 return new ImsCallSession(mImsServiceProxy.createCallSession(serviceId, profile, null));
Wink Savilleef36ef62014-06-11 08:39:38 -07001915 } catch (RemoteException e) {
Brad Ebingerb10b61e2017-04-18 11:45:26 -07001916 Rlog.w(TAG, "CreateCallSession: Error, remote exception: " + e.getMessage());
1917 throw new ImsException("createCallSession()", e,
1918 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1919
Wink Savilleef36ef62014-06-11 08:39:38 -07001920 }
1921 }
1922
Etan Cohena00c9192014-12-23 15:02:29 -08001923 private static void log(String s) {
Wink Savilleef36ef62014-06-11 08:39:38 -07001924 Rlog.d(TAG, s);
1925 }
1926
Etan Cohena00c9192014-12-23 15:02:29 -08001927 private static void loge(String s) {
Wink Savilleef36ef62014-06-11 08:39:38 -07001928 Rlog.e(TAG, s);
1929 }
1930
Etan Cohena00c9192014-12-23 15:02:29 -08001931 private static void loge(String s, Throwable t) {
Wink Savilleef36ef62014-06-11 08:39:38 -07001932 Rlog.e(TAG, s, t);
1933 }
1934
1935 /**
ram7da5a112014-07-16 20:59:27 +05301936 * Used for turning on IMS.if its off already
1937 */
Etan Cohen82f78122014-12-15 10:10:14 -08001938 private void turnOnIms() throws ImsException {
Etan Cohen0c9c09e2014-07-25 11:09:12 -07001939 checkAndThrowExceptionIfServiceUnavailable();
1940
ram7da5a112014-07-16 20:59:27 +05301941 try {
Brad Ebingerb5f30c72017-02-17 14:54:31 -08001942 mImsServiceProxy.turnOnIms();
ram7da5a112014-07-16 20:59:27 +05301943 } catch (RemoteException e) {
1944 throw new ImsException("turnOnIms() ", e, ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1945 }
1946 }
1947
Omkar Kolangade75f3ca32014-10-24 11:10:52 -07001948 private boolean isImsTurnOffAllowed() {
Brad Ebinger479f52c2017-08-28 13:19:22 -07001949 return isTurnOffImsAllowedByPlatform()
1950 && (!isWfcEnabledByPlatform()
1951 || !isWfcEnabledByUser());
Omkar Kolangade75f3ca32014-10-24 11:10:52 -07001952 }
1953
Amit Mahajan9cba36d2016-08-11 10:17:23 -07001954 private void setLteFeatureValues(boolean turnOn) {
1955 log("setLteFeatureValues: " + turnOn);
Omkar Kolangade75f3ca32014-10-24 11:10:52 -07001956 try {
1957 ImsConfig config = getConfigInterface();
Amit Mahajan9cba36d2016-08-11 10:17:23 -07001958 if (config != null) {
Omkar Kolangade75f3ca32014-10-24 11:10:52 -07001959 config.setFeatureValue(ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_LTE,
Pavel Zhamaitsiakf4b90322016-01-26 14:34:09 -08001960 TelephonyManager.NETWORK_TYPE_LTE, turnOn ? 1 : 0, mImsConfigListener);
Pavel Zhamaitsiakff29b9d2016-04-15 12:16:57 -07001961
Brad Ebinger479f52c2017-08-28 13:19:22 -07001962 if (isVolteEnabledByPlatform()) {
1963 boolean ignoreDataEnabledChanged = getBooleanCarrierConfig(
Jack Yu57781852016-11-16 17:20:38 -08001964 CarrierConfigManager.KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS);
Brad Ebinger479f52c2017-08-28 13:19:22 -07001965 boolean enableViLte = turnOn && isVtEnabledByUser() &&
Jack Yu57781852016-11-16 17:20:38 -08001966 (ignoreDataEnabledChanged || isDataEnabled());
Pavel Zhamaitsiakff29b9d2016-04-15 12:16:57 -07001967 config.setFeatureValue(ImsConfig.FeatureConstants.FEATURE_TYPE_VIDEO_OVER_LTE,
1968 TelephonyManager.NETWORK_TYPE_LTE,
1969 enableViLte ? 1 : 0,
1970 mImsConfigListener);
1971 }
Etan Cohenb651fa52014-10-22 10:51:29 -07001972 }
Omkar Kolangade75f3ca32014-10-24 11:10:52 -07001973 } catch (ImsException e) {
Amit Mahajan9cba36d2016-08-11 10:17:23 -07001974 loge("setLteFeatureValues: exception ", e);
Etan Cohencfc784d2014-08-07 18:40:31 -07001975 }
Amit Mahajan9cba36d2016-08-11 10:17:23 -07001976 }
1977
1978 private void setAdvanced4GMode(boolean turnOn) throws ImsException {
1979 checkAndThrowExceptionIfServiceUnavailable();
1980
1981 // if turnOn: first set feature values then call turnOnIms()
1982 // if turnOff: only set feature values if IMS turn off is not allowed. If turn off is
1983 // allowed, first call turnOffIms() then set feature values
Etan Cohencfc784d2014-08-07 18:40:31 -07001984 if (turnOn) {
Amit Mahajan9cba36d2016-08-11 10:17:23 -07001985 setLteFeatureValues(turnOn);
1986 log("setAdvanced4GMode: turnOnIms");
Etan Cohencfc784d2014-08-07 18:40:31 -07001987 turnOnIms();
Amit Mahajan9cba36d2016-08-11 10:17:23 -07001988 } else {
1989 if (isImsTurnOffAllowed()) {
1990 log("setAdvanced4GMode: turnOffIms");
1991 turnOffIms();
1992 }
1993 setLteFeatureValues(turnOn);
Etan Cohencfc784d2014-08-07 18:40:31 -07001994 }
1995 }
1996
ram7da5a112014-07-16 20:59:27 +05301997 /**
1998 * Used for turning off IMS completely in order to make the device CSFB'ed.
1999 * Once turned off, all calls will be over CS.
2000 */
Etan Cohen82f78122014-12-15 10:10:14 -08002001 private void turnOffIms() throws ImsException {
Etan Cohen0c9c09e2014-07-25 11:09:12 -07002002 checkAndThrowExceptionIfServiceUnavailable();
2003
ram7da5a112014-07-16 20:59:27 +05302004 try {
Brad Ebingerb5f30c72017-02-17 14:54:31 -08002005 mImsServiceProxy.turnOffIms();
ram7da5a112014-07-16 20:59:27 +05302006 } catch (RemoteException e) {
2007 throw new ImsException("turnOffIms() ", e, ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
2008 }
2009 }
2010
Naveen Kalla525c3a22017-02-06 14:46:42 -08002011 private void addToRecentDisconnectReasons(ImsReasonInfo reason) {
2012 if (reason == null) return;
2013 while (mRecentDisconnectReasons.size() >= MAX_RECENT_DISCONNECT_REASONS) {
2014 mRecentDisconnectReasons.removeFirst();
2015 }
2016 mRecentDisconnectReasons.addLast(reason);
2017 }
2018
ram7da5a112014-07-16 20:59:27 +05302019 /**
Wink Savilleef36ef62014-06-11 08:39:38 -07002020 * Death recipient class for monitoring IMS service.
2021 */
2022 private class ImsServiceDeathRecipient implements IBinder.DeathRecipient {
2023 @Override
2024 public void binderDied() {
Brad Ebinger16780ff2017-01-26 11:18:21 -08002025 mImsServiceProxy = null;
Wink Savilleef36ef62014-06-11 08:39:38 -07002026 mUt = null;
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -05002027 mConfig = null;
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -07002028 mEcbm = null;
Tyler Gunn4d128b62016-04-13 15:44:38 -07002029 mMultiEndpoint = null;
Wink Savilleef36ef62014-06-11 08:39:38 -07002030 }
2031 }
2032
2033 /**
Brad Ebinger57b11892017-06-13 16:21:35 -07002034 * Stub implementation of the Registration listener that provides no functionality.
2035 */
2036 private class ImsRegistrationListenerBase extends IImsRegistrationListener.Stub {
2037
2038 @Override
2039 public void registrationConnected() throws RemoteException {
2040 }
2041
2042 @Override
2043 public void registrationProgressing() throws RemoteException {
2044 }
2045
2046 @Override
2047 public void registrationConnectedWithRadioTech(int imsRadioTech) throws RemoteException {
2048 }
2049
2050 @Override
2051 public void registrationProgressingWithRadioTech(int imsRadioTech) throws RemoteException {
2052 }
2053
2054 @Override
2055 public void registrationDisconnected(ImsReasonInfo imsReasonInfo) throws RemoteException {
2056 }
2057
2058 @Override
2059 public void registrationResumed() throws RemoteException {
2060 }
2061
2062 @Override
2063 public void registrationSuspended() throws RemoteException {
2064 }
2065
2066 @Override
2067 public void registrationServiceCapabilityChanged(int serviceClass, int event)
2068 throws RemoteException {
2069 }
2070
2071 @Override
2072 public void registrationFeatureCapabilityChanged(int serviceClass, int[] enabledFeatures,
2073 int[] disabledFeatures) throws RemoteException {
2074 }
2075
2076 @Override
2077 public void voiceMessageCountUpdate(int count) throws RemoteException {
2078 }
2079
2080 @Override
2081 public void registrationAssociatedUriChanged(Uri[] uris) throws RemoteException {
2082 }
2083
2084 @Override
2085 public void registrationChangeFailed(int targetAccessTech, ImsReasonInfo imsReasonInfo)
2086 throws RemoteException {
2087 }
2088 }
2089
2090 /**
Wink Savilleef36ef62014-06-11 08:39:38 -07002091 * Adapter class for {@link IImsRegistrationListener}.
2092 */
Naveen Kalla196fd3b2017-02-14 14:55:24 -08002093 private class ImsRegistrationListenerProxy extends IImsRegistrationListener.Stub {
Wink Savilleef36ef62014-06-11 08:39:38 -07002094
Omkar Kolangadea7ced642015-05-04 17:55:13 -07002095 @Deprecated
Wink Savilleef36ef62014-06-11 08:39:38 -07002096 public void registrationConnected() {
2097 if (DBG) {
2098 log("registrationConnected ::");
2099 }
2100
Brad Ebinger9a0280c2017-06-01 15:58:48 -07002101 synchronized (mRegistrationListeners) {
2102 mRegistrationListeners.forEach(l -> l.onImsConnected(
2103 ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN));
Wink Savilleef36ef62014-06-11 08:39:38 -07002104 }
2105 }
2106
Omkar Kolangadea7ced642015-05-04 17:55:13 -07002107 @Deprecated
Rekha Kumar14631742015-02-04 10:47:00 -08002108 public void registrationProgressing() {
Wink Savilleef36ef62014-06-11 08:39:38 -07002109 if (DBG) {
Rekha Kumar14631742015-02-04 10:47:00 -08002110 log("registrationProgressing ::");
Wink Savilleef36ef62014-06-11 08:39:38 -07002111 }
2112
Brad Ebinger9a0280c2017-06-01 15:58:48 -07002113 synchronized (mRegistrationListeners) {
2114 mRegistrationListeners.forEach(l -> l.onImsProgressing(
2115 ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN));
Rekha Kumar14631742015-02-04 10:47:00 -08002116 }
2117 }
2118
2119 @Override
Omkar Kolangadea7ced642015-05-04 17:55:13 -07002120 public void registrationConnectedWithRadioTech(int imsRadioTech) {
2121 // Note: imsRadioTech value maps to RIL_RADIO_TECHNOLOGY
2122 // values in ServiceState.java.
2123 if (DBG) {
2124 log("registrationConnectedWithRadioTech :: imsRadioTech=" + imsRadioTech);
2125 }
2126
Brad Ebinger9a0280c2017-06-01 15:58:48 -07002127 synchronized (mRegistrationListeners) {
2128 mRegistrationListeners.forEach(l -> l.onImsConnected(imsRadioTech));
Omkar Kolangadea7ced642015-05-04 17:55:13 -07002129 }
2130 }
2131
2132 @Override
2133 public void registrationProgressingWithRadioTech(int imsRadioTech) {
2134 // Note: imsRadioTech value maps to RIL_RADIO_TECHNOLOGY
2135 // values in ServiceState.java.
2136 if (DBG) {
2137 log("registrationProgressingWithRadioTech :: imsRadioTech=" + imsRadioTech);
2138 }
2139
Brad Ebinger9a0280c2017-06-01 15:58:48 -07002140 synchronized (mRegistrationListeners) {
2141 mRegistrationListeners.forEach(l -> l.onImsProgressing(imsRadioTech));
Omkar Kolangadea7ced642015-05-04 17:55:13 -07002142 }
2143 }
2144
2145 @Override
Rekha Kumar14631742015-02-04 10:47:00 -08002146 public void registrationDisconnected(ImsReasonInfo imsReasonInfo) {
2147 if (DBG) {
2148 log("registrationDisconnected :: imsReasonInfo" + imsReasonInfo);
2149 }
2150
Naveen Kalla525c3a22017-02-06 14:46:42 -08002151 addToRecentDisconnectReasons(imsReasonInfo);
Brad Ebinger9a0280c2017-06-01 15:58:48 -07002152 synchronized (mRegistrationListeners) {
2153 mRegistrationListeners.forEach(l -> l.onImsDisconnected(imsReasonInfo));
Wink Savilleef36ef62014-06-11 08:39:38 -07002154 }
2155 }
2156
2157 @Override
2158 public void registrationResumed() {
2159 if (DBG) {
2160 log("registrationResumed ::");
2161 }
2162
Brad Ebinger9a0280c2017-06-01 15:58:48 -07002163 synchronized (mRegistrationListeners) {
2164 mRegistrationListeners.forEach(ImsConnectionStateListener::onImsResumed);
Wink Savilleef36ef62014-06-11 08:39:38 -07002165 }
2166 }
2167
2168 @Override
2169 public void registrationSuspended() {
2170 if (DBG) {
2171 log("registrationSuspended ::");
2172 }
2173
Brad Ebinger9a0280c2017-06-01 15:58:48 -07002174 synchronized (mRegistrationListeners) {
2175 mRegistrationListeners.forEach(ImsConnectionStateListener::onImsSuspended);
Wink Savilleef36ef62014-06-11 08:39:38 -07002176 }
2177 }
2178
2179 @Override
2180 public void registrationServiceCapabilityChanged(int serviceClass, int event) {
2181 log("registrationServiceCapabilityChanged :: serviceClass=" +
2182 serviceClass + ", event=" + event);
2183
Brad Ebinger9a0280c2017-06-01 15:58:48 -07002184 synchronized (mRegistrationListeners) {
2185 mRegistrationListeners.forEach(l -> l.onImsConnected(
2186 ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN));
Wink Savilleef36ef62014-06-11 08:39:38 -07002187 }
2188 }
ram7da5a112014-07-16 20:59:27 +05302189
2190 @Override
2191 public void registrationFeatureCapabilityChanged(int serviceClass,
2192 int[] enabledFeatures, int[] disabledFeatures) {
2193 log("registrationFeatureCapabilityChanged :: serviceClass=" +
2194 serviceClass);
Brad Ebinger9a0280c2017-06-01 15:58:48 -07002195
2196 synchronized (mRegistrationListeners) {
2197 mRegistrationListeners.forEach(l -> l.onFeatureCapabilityChanged(serviceClass,
2198 enabledFeatures, disabledFeatures));
Libin.Tang@motorola.come2296782014-08-19 14:20:01 -05002199 }
ram7da5a112014-07-16 20:59:27 +05302200 }
2201
Shriram Ganeshd3adfad2015-05-31 10:06:15 -07002202 @Override
2203 public void voiceMessageCountUpdate(int count) {
2204 log("voiceMessageCountUpdate :: count=" + count);
2205
Brad Ebinger9a0280c2017-06-01 15:58:48 -07002206 synchronized (mRegistrationListeners) {
2207 mRegistrationListeners.forEach(l -> l.onVoiceMessageCountChanged(count));
Shriram Ganeshd3adfad2015-05-31 10:06:15 -07002208 }
2209 }
2210
Pavel Zhamaitsiak4de9cbb2016-02-11 17:21:05 -08002211 @Override
2212 public void registrationAssociatedUriChanged(Uri[] uris) {
2213 if (DBG) log("registrationAssociatedUriChanged ::");
2214
Brad Ebinger9a0280c2017-06-01 15:58:48 -07002215 synchronized (mRegistrationListeners) {
2216 mRegistrationListeners.forEach(l -> l.registrationAssociatedUriChanged(uris));
Pavel Zhamaitsiak4de9cbb2016-02-11 17:21:05 -08002217 }
2218 }
Meng Wangbb98b9b2016-12-07 16:27:15 -08002219
2220 @Override
2221 public void registrationChangeFailed(int targetAccessTech, ImsReasonInfo imsReasonInfo) {
2222 if (DBG) log("registrationChangeFailed :: targetAccessTech=" + targetAccessTech +
2223 ", imsReasonInfo=" + imsReasonInfo);
2224
Brad Ebinger9a0280c2017-06-01 15:58:48 -07002225 synchronized (mRegistrationListeners) {
2226 mRegistrationListeners.forEach(l -> l.onRegistrationChangeFailed(targetAccessTech,
2227 imsReasonInfo));
Meng Wangbb98b9b2016-12-07 16:27:15 -08002228 }
2229 }
Wink Savilleef36ef62014-06-11 08:39:38 -07002230 }
Tyler Gunn4d128b62016-04-13 15:44:38 -07002231
Brad Ebinger44fd8af2017-12-14 14:24:02 -08002232 // New API for Registration, uses ImsConnectionStateListener for backwards compatibility with
2233 // deprecated APIs.
2234 private class ImsRegistrationCallback extends IImsRegistrationCallback.Stub {
2235
2236 @Override
2237 public void onRegistered(int imsRadioTech) {
2238 if (DBG) log("onRegistered ::");
2239
2240 synchronized (mRegistrationListeners) {
2241 mRegistrationListeners.forEach(l -> l.onRegistered(imsRadioTech));
2242 }
2243 }
2244
2245 @Override
2246 public void onRegistering(int imsRadioTech) {
2247 if (DBG) log("onRegistering ::");
2248
2249 synchronized (mRegistrationListeners) {
2250 mRegistrationListeners.forEach(l -> l.onRegistering(imsRadioTech));
2251 }
2252 }
2253
2254 @Override
2255 public void onDeregistered(ImsReasonInfo imsReasonInfo) {
2256 if (DBG) log("onDeregistered ::");
2257
2258 synchronized (mRegistrationListeners) {
2259 mRegistrationListeners.forEach(l -> l.onDeregistered(imsReasonInfo));
2260 }
2261 }
2262
2263 @Override
2264 public void onTechnologyChangeFailed(int targetRadioTech, ImsReasonInfo imsReasonInfo) {
2265 if (DBG) log("onTechnologyChangeFailed :: targetAccessTech=" + targetRadioTech +
2266 ", imsReasonInfo=" + imsReasonInfo);
2267
2268 synchronized (mRegistrationListeners) {
2269 mRegistrationListeners.forEach(l -> l.onTechnologyChangeFailed(targetRadioTech,
2270 imsReasonInfo));
2271 }
2272 }
2273
2274 @Override
2275 public void onSubscriberAssociatedUriChanged(Uri[] uris) {
2276 if (DBG) log("onSubscriberAssociatedUriChanged");
2277 synchronized (mRegistrationListeners) {
2278 mRegistrationListeners.forEach(l -> l.onSubscriberAssociatedUriChanged(uris));
2279 }
2280 }
2281 }
2282
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -07002283 /**
2284 * Gets the ECBM interface to request ECBM exit.
2285 *
2286 * @param serviceId a service id which is obtained from {@link ImsManager#open}
2287 * @return the ECBM interface instance
2288 * @throws ImsException if getting the ECBM interface results in an error
2289 */
2290 public ImsEcbm getEcbmInterface(int serviceId) throws ImsException {
Brad Ebinger138b4a62017-06-20 16:29:50 -07002291 if (mEcbm != null && mEcbm.isBinderAlive()) {
2292 return mEcbm;
2293 }
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -07002294
Brad Ebinger138b4a62017-06-20 16:29:50 -07002295 checkAndThrowExceptionIfServiceUnavailable();
2296 try {
2297 IImsEcbm iEcbm = mImsServiceProxy.getEcbmInterface();
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -07002298
Brad Ebinger138b4a62017-06-20 16:29:50 -07002299 if (iEcbm == null) {
2300 throw new ImsException("getEcbmInterface()",
2301 ImsReasonInfo.CODE_ECBM_NOT_SUPPORTED);
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -07002302 }
Brad Ebinger138b4a62017-06-20 16:29:50 -07002303 mEcbm = new ImsEcbm(iEcbm);
2304 } catch (RemoteException e) {
2305 throw new ImsException("getEcbmInterface()", e,
2306 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -07002307 }
2308 return mEcbm;
2309 }
Pavel Zhamaitsiak8c065f52015-11-10 14:36:44 -08002310
Mohamed Abdalkader4d68a982018-01-10 13:29:26 -08002311 public void sendSms(int token, int messageRef, String format, String smsc, boolean isRetry,
2312 byte[] pdu) throws ImsException {
2313 try {
2314 mImsServiceProxy.sendSms(token, messageRef, format, smsc, isRetry, pdu);
2315 } catch (RemoteException e) {
2316 throw new ImsException("sendSms()", e, ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
2317 }
2318 }
2319
2320 public void acknowledgeSms(int token, int messageRef, int result) throws ImsException {
2321 try {
2322 mImsServiceProxy.acknowledgeSms(token, messageRef, result);
2323 } catch (RemoteException e) {
2324 throw new ImsException("acknowledgeSms()", e,
2325 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
2326 }
2327 }
2328
2329 public void acknowledgeSmsReport(int token, int messageRef, int result) throws ImsException{
2330 try {
2331 mImsServiceProxy.acknowledgeSmsReport(token, messageRef, result);
2332 } catch (RemoteException e) {
2333 throw new ImsException("acknowledgeSmsReport()", e,
2334 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
2335 }
2336 }
2337
2338 public String getSmsFormat() throws ImsException{
2339 try {
2340 return mImsServiceProxy.getSmsFormat();
2341 } catch (RemoteException e) {
2342 throw new ImsException("getSmsFormat()", e,
2343 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
2344 }
2345 }
2346
2347 public void setSmsListener(IImsSmsListener listener) throws ImsException {
2348 try {
2349 mImsServiceProxy.setSmsListener(listener);
2350 } catch (RemoteException e) {
2351 throw new ImsException("setSmsListener()", e,
2352 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
2353 }
2354 }
Mohamed Abdalkadere1453f42018-01-19 19:48:31 -08002355
Mohamed Abdalkader0e734e12018-01-23 13:11:00 -08002356 public void onSmsReady() throws ImsException{
2357 try {
2358 mImsServiceProxy.onSmsReady();
2359 } catch (RemoteException e) {
2360 throw new ImsException("onSmsReady()", e,
2361 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
2362 }
2363 }
2364
Mohamed Abdalkadere1453f42018-01-19 19:48:31 -08002365 public void addRegistrationCallback(ImsRegistrationImplBase.Callback callback) {
2366 // TODO: implement (coming in ag/3472519)
2367 }
2368
2369 public void addCapabilitiesCallback(ImsFeature.CapabilityCallback callback) {
2370 // TODO: implement (coming in ag/3472519)
2371 }
2372
Pavel Zhamaitsiak8c065f52015-11-10 14:36:44 -08002373 /**
Tyler Gunn4d128b62016-04-13 15:44:38 -07002374 * Gets the Multi-Endpoint interface to subscribe to multi-enpoint notifications..
2375 *
2376 * @param serviceId a service id which is obtained from {@link ImsManager#open}
2377 * @return the multi-endpoint interface instance
2378 * @throws ImsException if getting the multi-endpoint interface results in an error
2379 */
2380 public ImsMultiEndpoint getMultiEndpointInterface(int serviceId) throws ImsException {
Brad Ebinger138b4a62017-06-20 16:29:50 -07002381 if (mMultiEndpoint != null && mMultiEndpoint.isBinderAlive()) {
2382 return mMultiEndpoint;
Tyler Gunn4d128b62016-04-13 15:44:38 -07002383 }
Brad Ebinger138b4a62017-06-20 16:29:50 -07002384
2385 checkAndThrowExceptionIfServiceUnavailable();
2386 try {
2387 IImsMultiEndpoint iImsMultiEndpoint = mImsServiceProxy.getMultiEndpointInterface();
2388
2389 if (iImsMultiEndpoint == null) {
2390 throw new ImsException("getMultiEndpointInterface()",
2391 ImsReasonInfo.CODE_MULTIENDPOINT_NOT_SUPPORTED);
2392 }
2393 mMultiEndpoint = new ImsMultiEndpoint(iImsMultiEndpoint);
2394 } catch (RemoteException e) {
2395 throw new ImsException("getMultiEndpointInterface()", e,
2396 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
2397 }
2398
Tyler Gunn4d128b62016-04-13 15:44:38 -07002399 return mMultiEndpoint;
2400 }
2401
2402 /**
Pavel Zhamaitsiak8c065f52015-11-10 14:36:44 -08002403 * Resets ImsManager settings back to factory defaults.
2404 *
Brad Ebinger479f52c2017-08-28 13:19:22 -07002405 * @deprecated Doesn't support MSIM devices. Use {@link #factoryReset()} instead.
Brad Ebinger16417b42017-03-07 13:48:50 -08002406 *
Pavel Zhamaitsiak8c065f52015-11-10 14:36:44 -08002407 * @hide
2408 */
2409 public static void factoryReset(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -07002410 ImsManager mgr = ImsManager.getInstance(context,
2411 SubscriptionManager.getDefaultVoicePhoneId());
2412 if (mgr != null) {
2413 mgr.factoryReset();
2414 }
2415 loge("factoryReset: ImsManager null.");
Pavel Zhamaitsiak8c065f52015-11-10 14:36:44 -08002416 }
Jack Yu2f102bd2015-12-28 15:31:48 -08002417
Brad Ebinger16417b42017-03-07 13:48:50 -08002418 /**
2419 * Resets ImsManager settings back to factory defaults.
2420 *
2421 * @hide
2422 */
Brad Ebinger479f52c2017-08-28 13:19:22 -07002423 public void factoryReset() {
Brad Ebinger16417b42017-03-07 13:48:50 -08002424 // Set VoLTE to default
Malcolm Chen212ca652017-09-28 17:28:45 -07002425 SubscriptionManager.setSubscriptionProperty(getSubId(),
manabu, shimoda96aee542017-10-06 15:39:36 +09002426 SubscriptionManager.ENHANCED_4G_MODE_ENABLED,
2427 booleanToPropertyString(getBooleanCarrierConfig(
2428 CarrierConfigManager.KEY_ENHANCED_4G_LTE_ON_BY_DEFAULT_BOOL)));
Brad Ebinger16417b42017-03-07 13:48:50 -08002429
2430 // Set VoWiFi to default
Malcolm Chen212ca652017-09-28 17:28:45 -07002431 SubscriptionManager.setSubscriptionProperty(getSubId(),
2432 SubscriptionManager.WFC_IMS_ENABLED,
2433 booleanToPropertyString(getBooleanCarrierConfig(
2434 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ENABLED_BOOL)));
Brad Ebinger16417b42017-03-07 13:48:50 -08002435
2436 // Set VoWiFi mode to default
Malcolm Chen212ca652017-09-28 17:28:45 -07002437 SubscriptionManager.setSubscriptionProperty(getSubId(),
2438 SubscriptionManager.WFC_IMS_MODE,
2439 Integer.toString(getIntCarrierConfig(
2440 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_MODE_INT)));
Brad Ebinger16417b42017-03-07 13:48:50 -08002441
2442 // Set VoWiFi roaming to default
Malcolm Chen212ca652017-09-28 17:28:45 -07002443 SubscriptionManager.setSubscriptionProperty(getSubId(),
2444 SubscriptionManager.WFC_IMS_ROAMING_ENABLED,
2445 booleanToPropertyString(getBooleanCarrierConfig(
2446 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_ENABLED_BOOL)));
Brad Ebinger16417b42017-03-07 13:48:50 -08002447
2448 // Set VT to default
Malcolm Chen212ca652017-09-28 17:28:45 -07002449 SubscriptionManager.setSubscriptionProperty(getSubId(),
2450 SubscriptionManager.VT_IMS_ENABLED, booleanToPropertyString(true));
Brad Ebinger16417b42017-03-07 13:48:50 -08002451
2452 // Push settings to ImsConfig
Brad Ebinger479f52c2017-08-28 13:19:22 -07002453 updateImsServiceConfig(true);
Brad Ebinger16417b42017-03-07 13:48:50 -08002454 }
2455
Amit Mahajan24f7b162016-07-21 16:33:53 -07002456 private boolean isDataEnabled() {
Malcolm Chend0ef12c2017-12-20 11:38:25 -08002457 return new TelephonyManager(mContext, getSubId()).isMobileDataEnabled();
Amit Mahajan24f7b162016-07-21 16:33:53 -07002458 }
2459
2460 private boolean isVolteProvisioned() {
Malcolm Chen18837ff2017-10-25 17:05:41 -07002461 return getProvisionedBoolNoException(
2462 ImsConfig.ConfigConstants.VLT_SETTING_ENABLED);
Amit Mahajan24f7b162016-07-21 16:33:53 -07002463 }
2464
2465 private boolean isWfcProvisioned() {
Malcolm Chen18837ff2017-10-25 17:05:41 -07002466 return getProvisionedBoolNoException(
2467 ImsConfig.ConfigConstants.VOICE_OVER_WIFI_SETTING_ENABLED);
Amit Mahajan24f7b162016-07-21 16:33:53 -07002468 }
2469
2470 private boolean isVtProvisioned() {
Malcolm Chen18837ff2017-10-25 17:05:41 -07002471 return getProvisionedBoolNoException(
2472 ImsConfig.ConfigConstants.LVC_SETTING_ENABLED);
Jack Yu643ffe42016-07-08 14:25:46 -07002473 }
2474
Malcolm Chen212ca652017-09-28 17:28:45 -07002475 private static String booleanToPropertyString(boolean bool) {
2476 return bool ? "1" : "0";
2477 }
2478
2479
Jack Yu2f102bd2015-12-28 15:31:48 -08002480 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
2481 pw.println("ImsManager:");
2482 pw.println(" mPhoneId = " + mPhoneId);
2483 pw.println(" mConfigUpdated = " + mConfigUpdated);
Brad Ebinger16780ff2017-01-26 11:18:21 -08002484 pw.println(" mImsServiceProxy = " + mImsServiceProxy);
Amit Mahajan24f7b162016-07-21 16:33:53 -07002485 pw.println(" mDataEnabled = " + isDataEnabled());
Brad Ebinger479f52c2017-08-28 13:19:22 -07002486 pw.println(" ignoreDataEnabledChanged = " + getBooleanCarrierConfig(
Jack Yu57781852016-11-16 17:20:38 -08002487 CarrierConfigManager.KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS));
Jack Yu2f102bd2015-12-28 15:31:48 -08002488
Brad Ebinger479f52c2017-08-28 13:19:22 -07002489 pw.println(" isGbaValid = " + isGbaValid());
Jack Yu2f102bd2015-12-28 15:31:48 -08002490 pw.println(" isImsTurnOffAllowed = " + isImsTurnOffAllowed());
Brad Ebinger479f52c2017-08-28 13:19:22 -07002491 pw.println(" isNonTtyOrTtyOnVolteEnabled = " + isNonTtyOrTtyOnVolteEnabled());
Jack Yu2f102bd2015-12-28 15:31:48 -08002492
Brad Ebinger479f52c2017-08-28 13:19:22 -07002493 pw.println(" isVolteEnabledByPlatform = " + isVolteEnabledByPlatform());
2494 pw.println(" isVolteProvisionedOnDevice = " + isVolteProvisionedOnDevice());
Jack Yu2f102bd2015-12-28 15:31:48 -08002495 pw.println(" isEnhanced4gLteModeSettingEnabledByUser = " +
Brad Ebinger479f52c2017-08-28 13:19:22 -07002496 isEnhanced4gLteModeSettingEnabledByUser());
2497 pw.println(" isVtEnabledByPlatform = " + isVtEnabledByPlatform());
2498 pw.println(" isVtEnabledByUser = " + isVtEnabledByUser());
Jack Yu2f102bd2015-12-28 15:31:48 -08002499
Brad Ebinger479f52c2017-08-28 13:19:22 -07002500 pw.println(" isWfcEnabledByPlatform = " + isWfcEnabledByPlatform());
2501 pw.println(" isWfcEnabledByUser = " + isWfcEnabledByUser());
2502 pw.println(" getWfcMode = " + getWfcMode());
2503 pw.println(" isWfcRoamingEnabledByUser = " + isWfcRoamingEnabledByUser());
Jack Yu2f102bd2015-12-28 15:31:48 -08002504
Brad Ebinger479f52c2017-08-28 13:19:22 -07002505 pw.println(" isVtProvisionedOnDevice = " + isVtProvisionedOnDevice());
2506 pw.println(" isWfcProvisionedOnDevice = " + isWfcProvisionedOnDevice());
Jack Yu2f102bd2015-12-28 15:31:48 -08002507 pw.flush();
2508 }
Wink Savilleef36ef62014-06-11 08:39:38 -07002509}