blob: eaf973d511b2ddc3e6a9077ad5f693a169b0b58f [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;
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -070023import android.os.AsyncTask;
Brad Ebingerbe6cb672017-08-25 14:55:00 -070024import android.os.Handler;
Wink Savilleef36ef62014-06-11 08:39:38 -070025import android.os.IBinder;
Brad Ebingerbe6cb672017-08-25 14:55:00 -070026import android.os.Looper;
Wink Savilleef36ef62014-06-11 08:39:38 -070027import android.os.Message;
Naveen Kalla525c3a22017-02-06 14:46:42 -080028import android.os.Parcel;
Jonathan Basseri2acea6f2015-07-01 15:00:38 -070029import android.os.PersistableBundle;
Wink Savilleef36ef62014-06-11 08:39:38 -070030import android.os.RemoteException;
Etan Cohenaf55a402014-09-04 22:34:41 -070031import android.os.SystemProperties;
Etan Cohen82f78122014-12-15 10:10:14 -080032import android.provider.Settings;
33import android.telecom.TelecomManager;
Junda Liue7663c02015-06-23 11:16:26 -070034import android.telephony.CarrierConfigManager;
Mohamed Abdalkader415e6de2018-01-19 19:48:31 -080035import android.telephony.ims.internal.feature.ImsFeature;
36import android.telephony.ims.stub.ImsRegistrationImplBase;
Wink Savilleef36ef62014-06-11 08:39:38 -070037import android.telephony.Rlog;
Meng Wangbb98b9b2016-12-07 16:27:15 -080038import android.telephony.ServiceState;
Etan Cohen82f78122014-12-15 10:10:14 -080039import android.telephony.SubscriptionManager;
Etan Cohencfc784d2014-08-07 18:40:31 -070040import android.telephony.TelephonyManager;
Hall Liue511a202017-08-17 15:49:58 -070041import android.util.Log;
Wink Savilleef36ef62014-06-11 08:39:38 -070042
43import com.android.ims.internal.IImsCallSession;
Naveen Kalla525c3a22017-02-06 14:46:42 -080044import com.android.ims.internal.IImsConfig;
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -070045import com.android.ims.internal.IImsEcbm;
Tyler Gunn4d128b62016-04-13 15:44:38 -070046import com.android.ims.internal.IImsMultiEndpoint;
Brad Ebinger3418c132018-01-18 12:03:33 -080047import com.android.ims.internal.IImsRegistration;
Brad Ebinger0e170c72017-12-14 14:24:02 -080048import com.android.ims.internal.IImsRegistrationCallback;
Wink Savilleef36ef62014-06-11 08:39:38 -070049import com.android.ims.internal.IImsRegistrationListener;
Mohamed Abdalkaderf8800da2018-01-10 13:29:26 -080050import com.android.ims.internal.IImsServiceController;
51import com.android.ims.internal.IImsSmsListener;
Wink Savilleef36ef62014-06-11 08:39:38 -070052import com.android.ims.internal.IImsUt;
53import com.android.ims.internal.ImsCallSession;
Brad Ebinger16780ff2017-01-26 11:18:21 -080054import com.android.internal.annotations.VisibleForTesting;
Brad Ebingerbe6cb672017-08-25 14:55:00 -070055import com.android.internal.telephony.ExponentialBackoff;
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -050056
Jack Yu2f102bd2015-12-28 15:31:48 -080057import java.io.FileDescriptor;
58import java.io.PrintWriter;
Naveen Kalla525c3a22017-02-06 14:46:42 -080059import java.util.ArrayList;
Etan Cohend7727462014-07-12 14:54:10 -070060import java.util.HashMap;
Naveen Kalla525c3a22017-02-06 14:46:42 -080061import java.util.concurrent.ConcurrentLinkedDeque;
Brad Ebinger16780ff2017-01-26 11:18:21 -080062import java.util.HashSet;
Brad Ebinger16780ff2017-01-26 11:18:21 -080063import java.util.Set;
Brad Ebinger0e170c72017-12-14 14:24:02 -080064import java.util.concurrent.CopyOnWriteArraySet;
Etan Cohend7727462014-07-12 14:54:10 -070065
Wink Savilleef36ef62014-06-11 08:39:38 -070066/**
67 * Provides APIs for IMS services, such as initiating IMS calls, and provides access to
68 * the operator's IMS network. This class is the starting point for any IMS actions.
69 * You can acquire an instance of it with {@link #getInstance getInstance()}.</p>
70 * <p>The APIs in this class allows you to:</p>
71 *
72 * @hide
73 */
74public class ImsManager {
Etan Cohen19604c02014-08-11 14:32:57 -070075
Etan Cohenaf55a402014-09-04 22:34:41 -070076 /*
77 * Debug flag to override configuration flag
78 */
Etan Cohenb651fa52014-10-22 10:51:29 -070079 public static final String PROPERTY_DBG_VOLTE_AVAIL_OVERRIDE = "persist.dbg.volte_avail_ovr";
80 public static final int PROPERTY_DBG_VOLTE_AVAIL_OVERRIDE_DEFAULT = 0;
Etan Cohenea2b5832014-10-23 18:50:35 -070081 public static final String PROPERTY_DBG_VT_AVAIL_OVERRIDE = "persist.dbg.vt_avail_ovr";
82 public static final int PROPERTY_DBG_VT_AVAIL_OVERRIDE_DEFAULT = 0;
Etan Cohena00c9192014-12-23 15:02:29 -080083 public static final String PROPERTY_DBG_WFC_AVAIL_OVERRIDE = "persist.dbg.wfc_avail_ovr";
84 public static final int PROPERTY_DBG_WFC_AVAIL_OVERRIDE_DEFAULT = 0;
Meng Wang9352c432016-06-08 14:22:20 -070085 public static final String PROPERTY_DBG_ALLOW_IMS_OFF_OVERRIDE = "persist.dbg.allow_ims_off";
86 public static final int PROPERTY_DBG_ALLOW_IMS_OFF_OVERRIDE_DEFAULT = 0;
Etan Cohenaf55a402014-09-04 22:34:41 -070087
Wink Savilleef36ef62014-06-11 08:39:38 -070088 /**
Wink Savilleef36ef62014-06-11 08:39:38 -070089 * The result code to be sent back with the incoming call {@link PendingIntent}.
90 * @see #open(PendingIntent, ImsConnectionStateListener)
91 */
92 public static final int INCOMING_CALL_RESULT_CODE = 101;
93
94 /**
95 * Key to retrieve the call ID from an incoming call intent.
96 * @see #open(PendingIntent, ImsConnectionStateListener)
97 */
98 public static final String EXTRA_CALL_ID = "android:imsCallID";
99
100 /**
101 * Action to broadcast when ImsService is up.
102 * Internal use only.
Brad Ebinger16780ff2017-01-26 11:18:21 -0800103 * @deprecated
Wink Savilleef36ef62014-06-11 08:39:38 -0700104 * @hide
105 */
106 public static final String ACTION_IMS_SERVICE_UP =
107 "com.android.ims.IMS_SERVICE_UP";
108
109 /**
110 * Action to broadcast when ImsService is down.
111 * Internal use only.
Brad Ebinger16780ff2017-01-26 11:18:21 -0800112 * @deprecated
Wink Savilleef36ef62014-06-11 08:39:38 -0700113 * @hide
114 */
115 public static final String ACTION_IMS_SERVICE_DOWN =
116 "com.android.ims.IMS_SERVICE_DOWN";
117
118 /**
Pavel Zhamaitsiak0c2f15c2015-03-12 15:37:54 -0700119 * Action to broadcast when ImsService registration fails.
120 * Internal use only.
121 * @hide
122 */
123 public static final String ACTION_IMS_REGISTRATION_ERROR =
124 "com.android.ims.REGISTRATION_ERROR";
125
126 /**
Etan Cohend7727462014-07-12 14:54:10 -0700127 * Part of the ACTION_IMS_SERVICE_UP or _DOWN intents.
Etan Cohenabbd7882014-09-26 22:35:35 -0700128 * A long value; the phone ID corresponding to the IMS service coming up or down.
Etan Cohend7727462014-07-12 14:54:10 -0700129 * Internal use only.
130 * @hide
131 */
Etan Cohenabbd7882014-09-26 22:35:35 -0700132 public static final String EXTRA_PHONE_ID = "android:phone_id";
Etan Cohend7727462014-07-12 14:54:10 -0700133
134 /**
Wink Savilleef36ef62014-06-11 08:39:38 -0700135 * Action for the incoming call intent for the Phone app.
136 * Internal use only.
137 * @hide
138 */
139 public static final String ACTION_IMS_INCOMING_CALL =
140 "com.android.ims.IMS_INCOMING_CALL";
141
142 /**
143 * Part of the ACTION_IMS_INCOMING_CALL intents.
144 * An integer value; service identifier obtained from {@link ImsManager#open}.
145 * Internal use only.
146 * @hide
147 */
148 public static final String EXTRA_SERVICE_ID = "android:imsServiceId";
149
150 /**
151 * Part of the ACTION_IMS_INCOMING_CALL intents.
152 * An boolean value; Flag to indicate that the incoming call is a normal call or call for USSD.
153 * The value "true" indicates that the incoming call is for USSD.
154 * Internal use only.
155 * @hide
156 */
157 public static final String EXTRA_USSD = "android:ussd";
158
Shriram Ganeshd3adfad2015-05-31 10:06:15 -0700159 /**
160 * Part of the ACTION_IMS_INCOMING_CALL intents.
161 * A boolean value; Flag to indicate whether the call is an unknown
162 * dialing call. Such calls are originated by sending commands (like
163 * AT commands) directly to modem without Android involvement.
164 * Even though they are not incoming calls, they are propagated
165 * to Phone app using same ACTION_IMS_INCOMING_CALL intent.
166 * Internal use only.
167 * @hide
168 */
Anju Mathapati9c033792015-06-16 16:33:16 -0700169 public static final String EXTRA_IS_UNKNOWN_CALL = "android:isUnknown";
Shriram Ganeshd3adfad2015-05-31 10:06:15 -0700170
Wink Savilleef36ef62014-06-11 08:39:38 -0700171 private static final String TAG = "ImsManager";
172 private static final boolean DBG = true;
173
Wink Saville1e5a38a2014-10-23 10:24:46 -0700174 private static HashMap<Integer, ImsManager> sImsManagerInstances =
175 new HashMap<Integer, ImsManager>();
Etan Cohend7727462014-07-12 14:54:10 -0700176
Wink Savilleef36ef62014-06-11 08:39:38 -0700177 private Context mContext;
Brad Ebinger16417b42017-03-07 13:48:50 -0800178 private CarrierConfigManager mConfigManager;
Etan Cohenabbd7882014-09-26 22:35:35 -0700179 private int mPhoneId;
Brad Ebinger16780ff2017-01-26 11:18:21 -0800180 private final boolean mConfigDynamicBind;
Brad Ebingera7c32432017-11-06 15:19:27 -0800181 private ImsServiceProxy mImsServiceProxy = null;
Wink Savilleef36ef62014-06-11 08:39:38 -0700182 private ImsServiceDeathRecipient mDeathRecipient = new ImsServiceDeathRecipient();
183 // Ut interface for the supplementary service configuration
184 private ImsUt mUt = null;
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -0500185 // Interface to get/set ims config items
186 private ImsConfig mConfig = null;
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -0700187 private boolean mConfigUpdated = false;
Wink Savilleef36ef62014-06-11 08:39:38 -0700188
Pavel Zhamaitsiakf4b90322016-01-26 14:34:09 -0800189 private ImsConfigListener mImsConfigListener;
190
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -0700191 // ECBM interface
192 private ImsEcbm mEcbm = null;
193
Tyler Gunn4d128b62016-04-13 15:44:38 -0700194 private ImsMultiEndpoint mMultiEndpoint = null;
195
Brad Ebinger0e170c72017-12-14 14:24:02 -0800196 private Set<ImsServiceProxy.IFeatureUpdate> mStatusCallbacks = new CopyOnWriteArraySet<>();
Brad Ebinger16780ff2017-01-26 11:18:21 -0800197
198 // Keep track of the ImsRegistrationListenerProxys that have been created so that we can
199 // remove them from the ImsService.
Brad Ebinger9a0280c2017-06-01 15:58:48 -0700200 private final Set<ImsConnectionStateListener> mRegistrationListeners = new HashSet<>();
201
Brad Ebinger0e170c72017-12-14 14:24:02 -0800202
203 // Used for compatibility with the old Registration method
204 // TODO: Remove once the compat layer is in place
205 private final ImsRegistrationListenerProxy mImsRegistrationListenerProxy =
Brad Ebinger9a0280c2017-06-01 15:58:48 -0700206 new ImsRegistrationListenerProxy();
Brad Ebinger0e170c72017-12-14 14:24:02 -0800207 // New API for registration to the ImsService.
208 private final ImsRegistrationCallback mRegistrationCallback = new ImsRegistrationCallback();
209
Brad Ebinger9a0280c2017-06-01 15:58:48 -0700210
211 // When true, we have registered the mRegistrationListenerProxy with the ImsService. Don't do
212 // it again.
213 private boolean mHasRegisteredForProxy = false;
214 private final Object mHasRegisteredLock = new Object();
Brad Ebinger16780ff2017-01-26 11:18:21 -0800215
Amit Mahajan24f7b162016-07-21 16:33:53 -0700216 // SystemProperties used as cache
217 private static final String VOLTE_PROVISIONED_PROP = "net.lte.ims.volte.provisioned";
218 private static final String WFC_PROVISIONED_PROP = "net.lte.ims.wfc.provisioned";
219 private static final String VT_PROVISIONED_PROP = "net.lte.ims.vt.provisioned";
Jack Yu643ffe42016-07-08 14:25:46 -0700220 // Flag indicating data enabled or not. This flag should be in sync with
221 // DcTracker.isDataEnabled(). The flag will be set later during boot up.
Amit Mahajan24f7b162016-07-21 16:33:53 -0700222 private static final String DATA_ENABLED_PROP = "net.lte.ims.data.enabled";
223
224 public static final String TRUE = "true";
225 public static final String FALSE = "false";
Jack Yu643ffe42016-07-08 14:25:46 -0700226
Naveen Kalla525c3a22017-02-06 14:46:42 -0800227 // mRecentDisconnectReasons stores the last 16 disconnect reasons
228 private static final int MAX_RECENT_DISCONNECT_REASONS = 16;
229 private ConcurrentLinkedDeque<ImsReasonInfo> mRecentDisconnectReasons =
230 new ConcurrentLinkedDeque<>();
231
Brad Ebingerbe6cb672017-08-25 14:55:00 -0700232 // Exponential backoff for provisioning cache update. May be null for instances of ImsManager
233 // that are not on a thread supporting a looper.
234 private ExponentialBackoff mProvisionBackoff;
235 // Initial Provisioning check delay in ms
236 private static final long BACKOFF_INITIAL_DELAY_MS = 500;
237 // Max Provisioning check delay in ms (5 Minutes)
238 private static final long BACKOFF_MAX_DELAY_MS = 300000;
239 // Multiplier for exponential delay
240 private static final int BACKOFF_MULTIPLIER = 2;
Malcolm Chen201d2312017-09-28 17:28:45 -0700241 // -1 indicates a subscriptionProperty value that is never set.
242 private static final int SUB_PROPERTY_NOT_INITIALIZED = -1;
Brad Ebingerbe6cb672017-08-25 14:55:00 -0700243
244
Wink Savilleef36ef62014-06-11 08:39:38 -0700245 /**
246 * Gets a manager instance.
247 *
248 * @param context application context for creating the manager object
Etan Cohenabbd7882014-09-26 22:35:35 -0700249 * @param phoneId the phone ID for the IMS Service
250 * @return the manager instance corresponding to the phoneId
Wink Savilleef36ef62014-06-11 08:39:38 -0700251 */
Etan Cohenabbd7882014-09-26 22:35:35 -0700252 public static ImsManager getInstance(Context context, int phoneId) {
Etan Cohend7727462014-07-12 14:54:10 -0700253 synchronized (sImsManagerInstances) {
Naveen Kalla525c3a22017-02-06 14:46:42 -0800254 if (sImsManagerInstances.containsKey(phoneId)) {
Brad Ebingerff097922017-06-19 15:43:08 -0700255 ImsManager m = sImsManagerInstances.get(phoneId);
256 // May be null for some tests
257 if (m != null) {
258 m.connectIfServiceIsAvailable();
259 }
260 return m;
Naveen Kalla525c3a22017-02-06 14:46:42 -0800261 }
Wink Savilleef36ef62014-06-11 08:39:38 -0700262
Etan Cohenabbd7882014-09-26 22:35:35 -0700263 ImsManager mgr = new ImsManager(context, phoneId);
264 sImsManagerInstances.put(phoneId, mgr);
Etan Cohend7727462014-07-12 14:54:10 -0700265
266 return mgr;
267 }
Wink Savilleef36ef62014-06-11 08:39:38 -0700268 }
269
Etan Cohen45b5f312014-08-19 15:55:08 -0700270 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800271 * Returns the user configuration of Enhanced 4G LTE Mode setting.
272 *
273 * @deprecated Doesn't support MSIM devices. Use
Brad Ebinger479f52c2017-08-28 13:19:22 -0700274 * {@link #isEnhanced4gLteModeSettingEnabledByUser()} instead.
Etan Cohen45b5f312014-08-19 15:55:08 -0700275 */
276 public static boolean isEnhanced4gLteModeSettingEnabledByUser(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700277 ImsManager mgr = ImsManager.getInstance(context,
278 SubscriptionManager.getDefaultVoicePhoneId());
279 if (mgr != null) {
280 return mgr.isEnhanced4gLteModeSettingEnabledByUser();
Sungmin Choi2f1af952016-02-01 17:15:35 +0900281 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700282 loge("isEnhanced4gLteModeSettingEnabledByUser: ImsManager null, returning default value.");
283 return false;
Etan Cohen45b5f312014-08-19 15:55:08 -0700284 }
285
286 /**
manabu, shimoda2335b702017-10-06 15:39:36 +0900287 * Returns the user configuration of Enhanced 4G LTE Mode setting for slot. If the option is
288 * not editable ({@link CarrierConfigManager#KEY_EDITABLE_ENHANCED_4G_LTE_BOOL} is false),
289 * this method will return default value specified by
290 * {@link CarrierConfigManager#KEY_ENHANCED_4G_LTE_ON_BY_DEFAULT_BOOL}.
Brad Ebinger16417b42017-03-07 13:48:50 -0800291 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700292 public boolean isEnhanced4gLteModeSettingEnabledByUser() {
Malcolm Chen201d2312017-09-28 17:28:45 -0700293 int setting = SubscriptionManager.getIntegerSubscriptionProperty(
294 getSubId(), SubscriptionManager.ENHANCED_4G_MODE_ENABLED,
295 SUB_PROPERTY_NOT_INITIALIZED, mContext);
296 boolean onByDefault = getBooleanCarrierConfig(
297 CarrierConfigManager.KEY_ENHANCED_4G_LTE_ON_BY_DEFAULT_BOOL);
298
299 // If Enhanced 4G LTE Mode is uneditable or not initialized, we use the default value
300 if (!getBooleanCarrierConfig(CarrierConfigManager.KEY_EDITABLE_ENHANCED_4G_LTE_BOOL)
301 || setting == SUB_PROPERTY_NOT_INITIALIZED) {
302 return onByDefault;
303 } else {
304 return (setting == ImsConfig.FeatureValueConstants.ON);
Brad Ebinger16417b42017-03-07 13:48:50 -0800305 }
Brad Ebinger16417b42017-03-07 13:48:50 -0800306 }
307
308 /**
309 * Change persistent Enhanced 4G LTE Mode setting.
310 *
Brad Ebinger479f52c2017-08-28 13:19:22 -0700311 * @deprecated Doesn't support MSIM devices. Use {@link #setEnhanced4gLteModeSetting(boolean)}
Brad Ebinger16417b42017-03-07 13:48:50 -0800312 * instead.
Etan Cohen82f78122014-12-15 10:10:14 -0800313 */
314 public static void setEnhanced4gLteModeSetting(Context context, boolean enabled) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700315 ImsManager mgr = ImsManager.getInstance(context,
316 SubscriptionManager.getDefaultVoicePhoneId());
317 if (mgr != null) {
318 mgr.setEnhanced4gLteModeSetting(enabled);
Etan Cohen82f78122014-12-15 10:10:14 -0800319 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700320 loge("setEnhanced4gLteModeSetting: ImsManager null, value not set.");
Etan Cohen82f78122014-12-15 10:10:14 -0800321 }
322
323 /**
manabu, shimoda2335b702017-10-06 15:39:36 +0900324 * Change persistent Enhanced 4G LTE Mode setting. If the option is not editable
Brad Ebinger16417b42017-03-07 13:48:50 -0800325 * ({@link CarrierConfigManager#KEY_EDITABLE_ENHANCED_4G_LTE_BOOL} is false), this method will
manabu, shimoda2335b702017-10-06 15:39:36 +0900326 * set the setting to the default value specified by
327 * {@link CarrierConfigManager#KEY_ENHANCED_4G_LTE_ON_BY_DEFAULT_BOOL}.
Brad Ebinger16417b42017-03-07 13:48:50 -0800328 *
329 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700330 public void setEnhanced4gLteModeSetting(boolean enabled) {
manabu, shimoda2335b702017-10-06 15:39:36 +0900331 // If editable=false, we must keep default advanced 4G mode.
332 if (!getBooleanCarrierConfig(CarrierConfigManager.KEY_EDITABLE_ENHANCED_4G_LTE_BOOL)) {
Malcolm Chen201d2312017-09-28 17:28:45 -0700333 enabled = getBooleanCarrierConfig(
334 CarrierConfigManager.KEY_ENHANCED_4G_LTE_ON_BY_DEFAULT_BOOL);
manabu, shimoda2335b702017-10-06 15:39:36 +0900335 }
Brad Ebinger16417b42017-03-07 13:48:50 -0800336
Malcolm Chen201d2312017-09-28 17:28:45 -0700337 int prevSetting = SubscriptionManager.getIntegerSubscriptionProperty(
338 getSubId(), SubscriptionManager.ENHANCED_4G_MODE_ENABLED,
339 SUB_PROPERTY_NOT_INITIALIZED, mContext);
Brad Ebinger16417b42017-03-07 13:48:50 -0800340
Malcolm Chen201d2312017-09-28 17:28:45 -0700341 if (prevSetting != (enabled ?
342 ImsConfig.FeatureValueConstants.ON :
343 ImsConfig.FeatureValueConstants.OFF)) {
344 SubscriptionManager.setSubscriptionProperty(getSubId(),
345 SubscriptionManager.ENHANCED_4G_MODE_ENABLED, booleanToPropertyString(enabled));
346 if (isNonTtyOrTtyOnVolteEnabled()) {
347 try {
348 setAdvanced4GMode(enabled);
349 } catch (ImsException ie) {
350 // do nothing
351 }
Brad Ebinger16417b42017-03-07 13:48:50 -0800352 }
353 }
354 }
355
356 /**
Etan Cohen82f78122014-12-15 10:10:14 -0800357 * Indicates whether the call is non-TTY or if TTY - whether TTY on VoLTE is
358 * supported.
Brad Ebinger16417b42017-03-07 13:48:50 -0800359 * @deprecated Does not support MSIM devices. Please use
Brad Ebinger479f52c2017-08-28 13:19:22 -0700360 * {@link #isNonTtyOrTtyOnVolteEnabled()} instead.
Etan Cohen82f78122014-12-15 10:10:14 -0800361 */
362 public static boolean isNonTtyOrTtyOnVolteEnabled(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700363 ImsManager mgr = ImsManager.getInstance(context,
364 SubscriptionManager.getDefaultVoicePhoneId());
365 if (mgr != null) {
366 return mgr.isNonTtyOrTtyOnVolteEnabled();
367 }
368 loge("isNonTtyOrTtyOnVolteEnabled: ImsManager null, returning default value.");
369 return false;
370 }
371
372 /**
373 * Indicates whether the call is non-TTY or if TTY - whether TTY on VoLTE is
374 * supported on a per slot basis.
375 */
376 public boolean isNonTtyOrTtyOnVolteEnabled() {
377 if (getBooleanCarrierConfig(
fionaxu5803ef02016-03-08 11:48:48 -0800378 CarrierConfigManager.KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL)) {
Etan Cohen82f78122014-12-15 10:10:14 -0800379 return true;
380 }
381
Brad Ebinger479f52c2017-08-28 13:19:22 -0700382 TelecomManager tm = (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
Hall Liue511a202017-08-17 15:49:58 -0700383 if (tm == null) {
384 Log.w(TAG, "isNonTtyOrTtyOnVolteEnabled: telecom not available");
385 return true;
386 }
387 return tm.getCurrentTtyMode() == TelecomManager.TTY_MODE_OFF;
Etan Cohen82f78122014-12-15 10:10:14 -0800388 }
389
390 /**
Etan Cohenea2b5832014-10-23 18:50:35 -0700391 * Returns a platform configuration for VoLTE which may override the user setting.
Brad Ebinger16417b42017-03-07 13:48:50 -0800392 * @deprecated Does not support MSIM devices. Please use
Brad Ebinger479f52c2017-08-28 13:19:22 -0700393 * {@link #isVolteEnabledByPlatform()} instead.
Etan Cohen45b5f312014-08-19 15:55:08 -0700394 */
Etan Cohenea2b5832014-10-23 18:50:35 -0700395 public static boolean isVolteEnabledByPlatform(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700396 ImsManager mgr = ImsManager.getInstance(context,
397 SubscriptionManager.getDefaultVoicePhoneId());
398 if (mgr != null) {
399 return mgr.isVolteEnabledByPlatform();
Etan Cohenaf55a402014-09-04 22:34:41 -0700400 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700401 loge("isVolteEnabledByPlatform: ImsManager null, returning default value.");
402 return false;
Etan Cohenb5388a32014-11-26 11:57:47 -0800403 }
404
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700405 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800406 * Returns a platform configuration for VoLTE which may override the user setting on a per Slot
407 * basis.
408 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700409 public boolean isVolteEnabledByPlatform() {
Brad Ebinger16417b42017-03-07 13:48:50 -0800410 if (SystemProperties.getInt(PROPERTY_DBG_VOLTE_AVAIL_OVERRIDE,
411 PROPERTY_DBG_VOLTE_AVAIL_OVERRIDE_DEFAULT) == 1) {
412 return true;
413 }
414
415 return mContext.getResources().getBoolean(
416 com.android.internal.R.bool.config_device_volte_available)
Malcolm Chen201d2312017-09-28 17:28:45 -0700417 && getBooleanCarrierConfig(CarrierConfigManager.KEY_CARRIER_VOLTE_AVAILABLE_BOOL)
Brad Ebinger479f52c2017-08-28 13:19:22 -0700418 && isGbaValid();
Brad Ebinger16417b42017-03-07 13:48:50 -0800419 }
420
421 /**
422 * Indicates whether VoLTE is provisioned on device.
423 *
424 * @deprecated Does not support MSIM devices. Please use
Brad Ebinger479f52c2017-08-28 13:19:22 -0700425 * {@link #isVolteProvisionedOnDevice()} instead.
Etan Cohenb5388a32014-11-26 11:57:47 -0800426 */
427 public static boolean isVolteProvisionedOnDevice(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700428 ImsManager mgr = ImsManager.getInstance(context,
429 SubscriptionManager.getDefaultVoicePhoneId());
430 if (mgr != null) {
431 return mgr.isVolteProvisionedOnDevice();
Etan Cohenb5388a32014-11-26 11:57:47 -0800432 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700433 loge("isVolteProvisionedOnDevice: ImsManager null, returning default value.");
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700434 return true;
435 }
436
437 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800438 * Indicates whether VoLTE is provisioned on this slot.
439 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700440 public boolean isVolteProvisionedOnDevice() {
441 if (getBooleanCarrierConfig(
Brad Ebinger16417b42017-03-07 13:48:50 -0800442 CarrierConfigManager.KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL)) {
443 return isVolteProvisioned();
444 }
445
446 return true;
447 }
448
449 /**
Meng Wang54fd41a2017-04-12 11:44:47 -0700450 * Indicates whether VoWifi is provisioned on device.
451 *
452 * When CarrierConfig KEY_CARRIER_VOLTE_OVERRIDE_WFC_PROVISIONING_BOOL is true, and VoLTE is not
453 * provisioned on device, this method returns false.
Brad Ebinger16417b42017-03-07 13:48:50 -0800454 *
455 * @deprecated Does not support MSIM devices. Please use
Brad Ebinger479f52c2017-08-28 13:19:22 -0700456 * {@link #isWfcProvisionedOnDevice()} instead.
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700457 */
458 public static boolean isWfcProvisionedOnDevice(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700459 ImsManager mgr = ImsManager.getInstance(context,
460 SubscriptionManager.getDefaultVoicePhoneId());
461 if (mgr != null) {
462 return mgr.isWfcProvisionedOnDevice();
Meng Wang54fd41a2017-04-12 11:44:47 -0700463 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700464 loge("isWfcProvisionedOnDevice: ImsManager null, returning default value.");
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700465 return true;
466 }
467
468 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800469 * Indicates whether VoWifi is provisioned on slot.
Meng Wang54fd41a2017-04-12 11:44:47 -0700470 *
471 * When CarrierConfig KEY_CARRIER_VOLTE_OVERRIDE_WFC_PROVISIONING_BOOL is true, and VoLTE is not
472 * provisioned on device, this method returns false.
Brad Ebinger16417b42017-03-07 13:48:50 -0800473 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700474 public boolean isWfcProvisionedOnDevice() {
475 if (getBooleanCarrierConfig(
Meng Wang54fd41a2017-04-12 11:44:47 -0700476 CarrierConfigManager.KEY_CARRIER_VOLTE_OVERRIDE_WFC_PROVISIONING_BOOL)) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700477 if (!isVolteProvisionedOnDevice()) {
Meng Wang54fd41a2017-04-12 11:44:47 -0700478 return false;
479 }
480 }
481
Brad Ebinger479f52c2017-08-28 13:19:22 -0700482 if (getBooleanCarrierConfig(
Brad Ebinger16417b42017-03-07 13:48:50 -0800483 CarrierConfigManager.KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL)) {
Meng Wang54fd41a2017-04-12 11:44:47 -0700484 return isWfcProvisioned();
Brad Ebinger16417b42017-03-07 13:48:50 -0800485 }
486
487 return true;
488 }
489
490 /**
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700491 * Indicates whether VT is provisioned on device
Brad Ebinger16417b42017-03-07 13:48:50 -0800492 *
493 * @deprecated Does not support MSIM devices. Please use
Brad Ebinger479f52c2017-08-28 13:19:22 -0700494 * {@link #isVtProvisionedOnDevice()} instead.
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700495 */
496 public static boolean isVtProvisionedOnDevice(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700497 ImsManager mgr = ImsManager.getInstance(context,
498 SubscriptionManager.getDefaultVoicePhoneId());
499 if (mgr != null) {
500 return mgr.isVtProvisionedOnDevice();
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700501 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700502 loge("isVtProvisionedOnDevice: ImsManager null, returning default value.");
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700503 return true;
Etan Cohenb651fa52014-10-22 10:51:29 -0700504 }
505
Etan Cohenea2b5832014-10-23 18:50:35 -0700506 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800507 * Indicates whether VT is provisioned on slot.
508 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700509 public boolean isVtProvisionedOnDevice() {
510 if (getBooleanCarrierConfig(
Brad Ebinger16417b42017-03-07 13:48:50 -0800511 CarrierConfigManager.KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL)) {
512 return isVtProvisioned();
513 }
514
515 return true;
516 }
517
518 /**
Etan Cohenea2b5832014-10-23 18:50:35 -0700519 * Returns a platform configuration for VT which may override the user setting.
520 *
521 * Note: VT presumes that VoLTE is enabled (these are configuration settings
522 * which must be done correctly).
Brad Ebinger16417b42017-03-07 13:48:50 -0800523 *
524 * @deprecated Does not support MSIM devices. Please use
Brad Ebinger479f52c2017-08-28 13:19:22 -0700525 * {@link #isVtEnabledByPlatform()} instead.
Etan Cohenea2b5832014-10-23 18:50:35 -0700526 */
Etan Cohenb651fa52014-10-22 10:51:29 -0700527 public static boolean isVtEnabledByPlatform(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700528 ImsManager mgr = ImsManager.getInstance(context,
529 SubscriptionManager.getDefaultVoicePhoneId());
530 if (mgr != null) {
531 return mgr.isVtEnabledByPlatform();
Etan Cohenea2b5832014-10-23 18:50:35 -0700532 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700533 loge("isVtEnabledByPlatform: ImsManager null, returning default value.");
534 return false;
Etan Cohen45b5f312014-08-19 15:55:08 -0700535 }
536
Etan Cohena00c9192014-12-23 15:02:29 -0800537 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800538 * Returns a platform configuration for VT which may override the user setting.
539 *
540 * Note: VT presumes that VoLTE is enabled (these are configuration settings
541 * which must be done correctly).
542 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700543 public boolean isVtEnabledByPlatform() {
Brad Ebinger16417b42017-03-07 13:48:50 -0800544 if (SystemProperties.getInt(PROPERTY_DBG_VT_AVAIL_OVERRIDE,
545 PROPERTY_DBG_VT_AVAIL_OVERRIDE_DEFAULT) == 1) {
546 return true;
547 }
548
549 return mContext.getResources().getBoolean(
550 com.android.internal.R.bool.config_device_vt_available) &&
Malcolm Chen201d2312017-09-28 17:28:45 -0700551 getBooleanCarrierConfig(CarrierConfigManager.KEY_CARRIER_VT_AVAILABLE_BOOL) &&
Brad Ebinger479f52c2017-08-28 13:19:22 -0700552 isGbaValid();
Brad Ebinger16417b42017-03-07 13:48:50 -0800553 }
554
555 /**
Etan Cohena7d32e82015-05-04 18:02:09 -0700556 * Returns the user configuration of VT setting
Brad Ebinger16417b42017-03-07 13:48:50 -0800557 * @deprecated Does not support MSIM devices. Please use
Brad Ebinger479f52c2017-08-28 13:19:22 -0700558 * {@link #isVtEnabledByUser()} instead.
Etan Cohena7d32e82015-05-04 18:02:09 -0700559 */
560 public static boolean isVtEnabledByUser(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700561 ImsManager mgr = ImsManager.getInstance(context,
562 SubscriptionManager.getDefaultVoicePhoneId());
563 if (mgr != null) {
564 return mgr.isVtEnabledByUser();
565 }
566 loge("isVtEnabledByUser: ImsManager null, returning default value.");
567 return false;
Etan Cohena7d32e82015-05-04 18:02:09 -0700568 }
569
570 /**
Malcolm Chen201d2312017-09-28 17:28:45 -0700571 * Returns the user configuration of VT setting per slot. If not set, it
572 * returns true as default value.
Brad Ebinger16417b42017-03-07 13:48:50 -0800573 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700574 public boolean isVtEnabledByUser() {
Malcolm Chen201d2312017-09-28 17:28:45 -0700575 int setting = SubscriptionManager.getIntegerSubscriptionProperty(
576 getSubId(), SubscriptionManager.VT_IMS_ENABLED,
577 SUB_PROPERTY_NOT_INITIALIZED, mContext);
578
579 // If it's never set, by default we return true.
580 return (setting == SUB_PROPERTY_NOT_INITIALIZED || setting == 1);
Brad Ebinger16417b42017-03-07 13:48:50 -0800581 }
582
583 /**
Etan Cohena7d32e82015-05-04 18:02:09 -0700584 * Change persistent VT enabled setting
Brad Ebinger16417b42017-03-07 13:48:50 -0800585 *
Brad Ebinger479f52c2017-08-28 13:19:22 -0700586 * @deprecated Does not support MSIM devices. Please use {@link #setVtSetting(boolean)} instead.
Etan Cohena7d32e82015-05-04 18:02:09 -0700587 */
588 public static void setVtSetting(Context context, boolean enabled) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700589 ImsManager mgr = ImsManager.getInstance(context,
Etan Cohena7d32e82015-05-04 18:02:09 -0700590 SubscriptionManager.getDefaultVoicePhoneId());
Brad Ebinger479f52c2017-08-28 13:19:22 -0700591 if (mgr != null) {
592 mgr.setVtSetting(enabled);
Etan Cohena7d32e82015-05-04 18:02:09 -0700593 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700594 loge("setVtSetting: ImsManager null, can not set value.");
Etan Cohena7d32e82015-05-04 18:02:09 -0700595 }
596
Brad Ebinger16417b42017-03-07 13:48:50 -0800597 /**
598 * Change persistent VT enabled setting for slot.
599 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700600 public void setVtSetting(boolean enabled) {
Malcolm Chen201d2312017-09-28 17:28:45 -0700601 SubscriptionManager.setSubscriptionProperty(getSubId(),
602 SubscriptionManager.VT_IMS_ENABLED,
603 booleanToPropertyString(enabled));
Brad Ebinger16417b42017-03-07 13:48:50 -0800604 try {
605 ImsConfig config = getConfigInterface();
606 config.setFeatureValue(ImsConfig.FeatureConstants.FEATURE_TYPE_VIDEO_OVER_LTE,
607 TelephonyManager.NETWORK_TYPE_LTE,
608 enabled ? ImsConfig.FeatureValueConstants.ON
609 : ImsConfig.FeatureValueConstants.OFF,
610 mImsConfigListener);
611
612 if (enabled) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700613 log("setVtSetting(b) : turnOnIms");
Brad Ebinger16417b42017-03-07 13:48:50 -0800614 turnOnIms();
Brad Ebinger479f52c2017-08-28 13:19:22 -0700615 } else if (isVolteEnabledByPlatform()
616 && (!isVolteEnabledByPlatform()
617 || !isEnhanced4gLteModeSettingEnabledByUser())) {
618 log("setVtSetting(b) : imsServiceAllowTurnOff -> turnOffIms");
Brad Ebinger16417b42017-03-07 13:48:50 -0800619 turnOffIms();
620 }
621 } catch (ImsException e) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700622 loge("setVtSetting(b): ", e);
Brad Ebinger16417b42017-03-07 13:48:50 -0800623 }
624 }
625
626 /**
Meng Wang9352c432016-06-08 14:22:20 -0700627 * Returns whether turning off ims is allowed by platform.
628 * The platform property may override the carrier config.
Brad Ebinger16417b42017-03-07 13:48:50 -0800629 *
630 * @deprecated Does not support MSIM devices. Please use
Brad Ebinger479f52c2017-08-28 13:19:22 -0700631 * {@link #isTurnOffImsAllowedByPlatform()} instead.
Meng Wang9352c432016-06-08 14:22:20 -0700632 */
633 private static boolean isTurnOffImsAllowedByPlatform(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700634 ImsManager mgr = ImsManager.getInstance(context,
635 SubscriptionManager.getDefaultVoicePhoneId());
636 if (mgr != null) {
637 return mgr.isTurnOffImsAllowedByPlatform();
Meng Wang9352c432016-06-08 14:22:20 -0700638 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700639 loge("isTurnOffImsAllowedByPlatform: ImsManager null, returning default value.");
640 return true;
Meng Wang9352c432016-06-08 14:22:20 -0700641 }
642
Etan Cohena7d32e82015-05-04 18:02:09 -0700643 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800644 * Returns whether turning off ims is allowed by platform.
645 * The platform property may override the carrier config.
646 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700647 private boolean isTurnOffImsAllowedByPlatform() {
Brad Ebinger16417b42017-03-07 13:48:50 -0800648 if (SystemProperties.getInt(PROPERTY_DBG_ALLOW_IMS_OFF_OVERRIDE,
649 PROPERTY_DBG_ALLOW_IMS_OFF_OVERRIDE_DEFAULT) == 1) {
650 return true;
651 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700652 return getBooleanCarrierConfig(
Brad Ebinger16417b42017-03-07 13:48:50 -0800653 CarrierConfigManager.KEY_CARRIER_ALLOW_TURNOFF_IMS_BOOL);
654 }
655
656 /**
Etan Cohena00c9192014-12-23 15:02:29 -0800657 * Returns the user configuration of WFC setting
Brad Ebinger16417b42017-03-07 13:48:50 -0800658 *
659 * @deprecated Does not support MSIM devices. Please use
Brad Ebinger479f52c2017-08-28 13:19:22 -0700660 * {@link #isWfcEnabledByUser()} instead.
Etan Cohena00c9192014-12-23 15:02:29 -0800661 */
662 public static boolean isWfcEnabledByUser(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700663 ImsManager mgr = ImsManager.getInstance(context,
664 SubscriptionManager.getDefaultVoicePhoneId());
665 if (mgr != null) {
666 return mgr.isWfcEnabledByUser();
667 }
668 loge("isWfcEnabledByUser: ImsManager null, returning default value.");
669 return true;
Etan Cohena00c9192014-12-23 15:02:29 -0800670 }
671
672 /**
Malcolm Chen201d2312017-09-28 17:28:45 -0700673 * Returns the user configuration of WFC setting for slot. If not set, it
674 * queries CarrierConfig value as default.
Brad Ebinger16417b42017-03-07 13:48:50 -0800675 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700676 public boolean isWfcEnabledByUser() {
Malcolm Chen201d2312017-09-28 17:28:45 -0700677 int setting = SubscriptionManager.getIntegerSubscriptionProperty(
678 getSubId(), SubscriptionManager.WFC_IMS_ENABLED,
679 SUB_PROPERTY_NOT_INITIALIZED, mContext);
680
681 // SUB_PROPERTY_NOT_INITIALIZED indicates it's never set in sub db.
682 if (setting == SUB_PROPERTY_NOT_INITIALIZED) {
683 return getBooleanCarrierConfig(
684 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ENABLED_BOOL);
685 } else {
686 return setting == 1;
687 }
Brad Ebinger16417b42017-03-07 13:48:50 -0800688 }
689
690 /**
691 * Change persistent WFC enabled setting.
692 * @deprecated Does not support MSIM devices. Please use
Brad Ebinger479f52c2017-08-28 13:19:22 -0700693 * {@link #setWfcSetting} instead.
Etan Cohena00c9192014-12-23 15:02:29 -0800694 */
695 public static void setWfcSetting(Context context, boolean enabled) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700696 ImsManager mgr = ImsManager.getInstance(context,
Etan Cohena00c9192014-12-23 15:02:29 -0800697 SubscriptionManager.getDefaultVoicePhoneId());
Brad Ebinger479f52c2017-08-28 13:19:22 -0700698 if (mgr != null) {
699 mgr.setWfcSetting(enabled);
Etan Cohena00c9192014-12-23 15:02:29 -0800700 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700701 loge("setWfcSetting: ImsManager null, can not set value.");
Etan Cohena00c9192014-12-23 15:02:29 -0800702 }
703
704 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800705 * Change persistent WFC enabled setting for slot.
706 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700707 public void setWfcSetting(boolean enabled) {
Malcolm Chen201d2312017-09-28 17:28:45 -0700708 SubscriptionManager.setSubscriptionProperty(getSubId(),
709 SubscriptionManager.WFC_IMS_ENABLED, booleanToPropertyString(enabled));
Brad Ebinger16417b42017-03-07 13:48:50 -0800710
Brad Ebinger479f52c2017-08-28 13:19:22 -0700711 setWfcNonPersistent(enabled, getWfcMode());
Meng Wang51c09072017-03-27 10:47:45 -0700712 }
713
714 /**
715 * Non-persistently change WFC enabled setting and WFC mode for slot
716 *
717 * @param wfcMode The WFC preference if WFC is enabled
718 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700719 public void setWfcNonPersistent(boolean enabled, int wfcMode) {
Meng Wang51c09072017-03-27 10:47:45 -0700720 int imsFeatureValue =
721 enabled ? ImsConfig.FeatureValueConstants.ON : ImsConfig.FeatureValueConstants.OFF;
722 // Force IMS to register over LTE when turning off WFC
723 int imsWfcModeFeatureValue =
724 enabled ? wfcMode : ImsConfig.WfcModeFeatureValueConstants.CELLULAR_PREFERRED;
725
Brad Ebinger16417b42017-03-07 13:48:50 -0800726 try {
727 ImsConfig config = getConfigInterface();
728 config.setFeatureValue(ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_WIFI,
729 TelephonyManager.NETWORK_TYPE_IWLAN,
Meng Wang51c09072017-03-27 10:47:45 -0700730 imsFeatureValue,
Brad Ebinger16417b42017-03-07 13:48:50 -0800731 mImsConfigListener);
732
733 if (enabled) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700734 log("setWfcSetting() : turnOnIms");
Brad Ebinger16417b42017-03-07 13:48:50 -0800735 turnOnIms();
Brad Ebinger479f52c2017-08-28 13:19:22 -0700736 } else if (isTurnOffImsAllowedByPlatform()
737 && (!isVolteEnabledByPlatform()
738 || !isEnhanced4gLteModeSettingEnabledByUser())) {
739 log("setWfcSetting() : imsServiceAllowTurnOff -> turnOffIms");
Brad Ebinger16417b42017-03-07 13:48:50 -0800740 turnOffIms();
741 }
742
Brad Ebinger479f52c2017-08-28 13:19:22 -0700743 setWfcModeInternal(imsWfcModeFeatureValue);
Brad Ebinger16417b42017-03-07 13:48:50 -0800744 } catch (ImsException e) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700745 loge("setWfcSetting(): ", e);
Brad Ebinger16417b42017-03-07 13:48:50 -0800746 }
747 }
748
749 /**
750 * Returns the user configuration of WFC preference setting.
751 *
Malcolm Chen201d2312017-09-28 17:28:45 -0700752 * @deprecated Doesn't support MSIM devices. Use {@link #getWfcMode(boolean roaming)} instead.
Etan Cohena00c9192014-12-23 15:02:29 -0800753 */
754 public static int getWfcMode(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700755 ImsManager mgr = ImsManager.getInstance(context,
756 SubscriptionManager.getDefaultVoicePhoneId());
757 if (mgr != null) {
758 return mgr.getWfcMode();
759 }
760 loge("getWfcMode: ImsManager null, returning default value.");
761 return ImsConfig.WfcModeFeatureValueConstants.WIFI_ONLY;
Etan Cohena00c9192014-12-23 15:02:29 -0800762 }
763
764 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800765 * Returns the user configuration of WFC preference setting
Malcolm Chen201d2312017-09-28 17:28:45 -0700766 * @deprecated. Use {@link #getWfcMode(boolean roaming)} instead.
Brad Ebinger16417b42017-03-07 13:48:50 -0800767 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700768 public int getWfcMode() {
Malcolm Chen201d2312017-09-28 17:28:45 -0700769 return getWfcMode(false);
Brad Ebinger16417b42017-03-07 13:48:50 -0800770 }
771
772 /**
773 * Change persistent WFC preference setting.
774 *
Brad Ebinger479f52c2017-08-28 13:19:22 -0700775 * @deprecated Doesn't support MSIM devices. Use {@link #setWfcMode(int)} instead.
Etan Cohena00c9192014-12-23 15:02:29 -0800776 */
777 public static void setWfcMode(Context context, int wfcMode) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700778 ImsManager mgr = ImsManager.getInstance(context,
779 SubscriptionManager.getDefaultVoicePhoneId());
780 if (mgr != null) {
781 mgr.setWfcMode(wfcMode);
782 }
783 loge("setWfcMode: ImsManager null, can not set value.");
Pavel Zhamaitsiak9e6eca22015-03-16 15:30:53 -0700784 }
785
Meng Wang37477012016-09-20 09:59:56 -0700786 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800787 * Change persistent WFC preference setting for slot.
788 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700789 public void setWfcMode(int wfcMode) {
790 if (DBG) log("setWfcMode(i) - setting=" + wfcMode);
Malcolm Chen201d2312017-09-28 17:28:45 -0700791
792 SubscriptionManager.setSubscriptionProperty(getSubId(),
793 SubscriptionManager.WFC_IMS_MODE, Integer.toString(wfcMode));
Brad Ebinger16417b42017-03-07 13:48:50 -0800794
Brad Ebinger479f52c2017-08-28 13:19:22 -0700795 setWfcModeInternal(wfcMode);
Brad Ebinger16417b42017-03-07 13:48:50 -0800796 }
797
798 /**
Suresh Koleti76491082017-04-21 18:39:50 +0530799 * Changes the WFC mode to its default value for Carriers with non-editable WFC settings.
800 */
801 private void updateDefaultWfcMode() {
802 if (DBG) log("updateDefaultWfcMode");
Brad Ebinger479f52c2017-08-28 13:19:22 -0700803 if (!getBooleanCarrierConfig(CarrierConfigManager.KEY_EDITABLE_WFC_MODE_BOOL)) {
804 setWfcMode(getIntCarrierConfig(
Suresh Koleti76491082017-04-21 18:39:50 +0530805 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_MODE_INT));
806 }
807 }
808
809 /**
Meng Wang37477012016-09-20 09:59:56 -0700810 * Returns the user configuration of WFC preference setting
811 *
812 * @param roaming {@code false} for home network setting, {@code true} for roaming setting
Brad Ebinger16417b42017-03-07 13:48:50 -0800813 *
Brad Ebinger479f52c2017-08-28 13:19:22 -0700814 * @deprecated Doesn't support MSIM devices. Use {@link #getWfcMode(boolean)} instead.
Meng Wang37477012016-09-20 09:59:56 -0700815 */
816 public static int getWfcMode(Context context, boolean roaming) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700817 ImsManager mgr = ImsManager.getInstance(context,
818 SubscriptionManager.getDefaultVoicePhoneId());
819 if (mgr != null) {
820 return mgr.getWfcMode(roaming);
Meng Wang37477012016-09-20 09:59:56 -0700821 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700822 loge("getWfcMode: ImsManager null, returning default value.");
823 return ImsConfig.WfcModeFeatureValueConstants.WIFI_ONLY;
Meng Wang37477012016-09-20 09:59:56 -0700824 }
825
826 /**
Malcolm Chen201d2312017-09-28 17:28:45 -0700827 * Returns the user configuration of WFC preference setting for slot. If not set, it
828 * queries CarrierConfig value as default.
Brad Ebinger16417b42017-03-07 13:48:50 -0800829 *
830 * @param roaming {@code false} for home network setting, {@code true} for roaming setting
831 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700832 public int getWfcMode(boolean roaming) {
Brad Ebinger16417b42017-03-07 13:48:50 -0800833 int setting = 0;
834 if (!roaming) {
Malcolm Chen201d2312017-09-28 17:28:45 -0700835 setting = SubscriptionManager.getIntegerSubscriptionProperty(
836 getSubId(), SubscriptionManager.WFC_IMS_MODE,
837 SUB_PROPERTY_NOT_INITIALIZED, mContext);
838
839 // SUB_PROPERTY_NOT_INITIALIZED indicates it's never set in sub db.
840 if (setting == SUB_PROPERTY_NOT_INITIALIZED) {
841 setting = getIntCarrierConfig(
842 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_MODE_INT);
843 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700844 if (DBG) log("getWfcMode - setting=" + setting);
Brad Ebinger16417b42017-03-07 13:48:50 -0800845 } else {
Malcolm Chen201d2312017-09-28 17:28:45 -0700846 setting = SubscriptionManager.getIntegerSubscriptionProperty(
847 getSubId(), SubscriptionManager.WFC_IMS_ROAMING_MODE,
848 SUB_PROPERTY_NOT_INITIALIZED, mContext);
849
850 // SUB_PROPERTY_NOT_INITIALIZED indicates it's never set in sub db.
851 if (setting == SUB_PROPERTY_NOT_INITIALIZED) {
852 setting = getIntCarrierConfig(
853 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_MODE_INT);
854 }
855
Brad Ebinger479f52c2017-08-28 13:19:22 -0700856 if (DBG) log("getWfcMode (roaming) - setting=" + setting);
Brad Ebinger16417b42017-03-07 13:48:50 -0800857 }
858 return setting;
859 }
860
861 /**
Meng Wang37477012016-09-20 09:59:56 -0700862 * Change persistent WFC preference setting
863 *
864 * @param roaming {@code false} for home network setting, {@code true} for roaming setting
Brad Ebinger16417b42017-03-07 13:48:50 -0800865 *
Brad Ebinger479f52c2017-08-28 13:19:22 -0700866 * @deprecated Doesn't support MSIM devices. Please use {@link #setWfcMode(int, boolean)}
867 * instead.
Meng Wang37477012016-09-20 09:59:56 -0700868 */
869 public static void setWfcMode(Context context, int wfcMode, boolean roaming) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700870 ImsManager mgr = ImsManager.getInstance(context,
871 SubscriptionManager.getDefaultVoicePhoneId());
872 if (mgr != null) {
873 mgr.setWfcMode(wfcMode, roaming);
Meng Wang37477012016-09-20 09:59:56 -0700874 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700875 loge("setWfcMode: ImsManager null, can not set value.");
Meng Wang37477012016-09-20 09:59:56 -0700876 }
877
Brad Ebinger16417b42017-03-07 13:48:50 -0800878 /**
879 * Change persistent WFC preference setting
880 *
881 * @param roaming {@code false} for home network setting, {@code true} for roaming setting
882 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700883 public void setWfcMode(int wfcMode, boolean roaming) {
Brad Ebinger16417b42017-03-07 13:48:50 -0800884 if (!roaming) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700885 if (DBG) log("setWfcMode(i,b) - setting=" + wfcMode);
Malcolm Chen201d2312017-09-28 17:28:45 -0700886 SubscriptionManager.setSubscriptionProperty(getSubId(),
887 SubscriptionManager.WFC_IMS_MODE, Integer.toString(wfcMode));
Brad Ebinger16417b42017-03-07 13:48:50 -0800888 } else {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700889 if (DBG) log("setWfcMode(i,b) (roaming) - setting=" + wfcMode);
Malcolm Chen201d2312017-09-28 17:28:45 -0700890 SubscriptionManager.setSubscriptionProperty(getSubId(),
891 SubscriptionManager.WFC_IMS_ROAMING_MODE, Integer.toString(wfcMode));
Brad Ebinger16417b42017-03-07 13:48:50 -0800892 }
893
Brad Ebinger479f52c2017-08-28 13:19:22 -0700894 TelephonyManager tm = (TelephonyManager)
895 mContext.getSystemService(Context.TELEPHONY_SERVICE);
896 if (roaming == tm.isNetworkRoaming(getSubId())) {
897 setWfcModeInternal(wfcMode);
898 }
899 }
900
901 private int getSubId() {
Brad Ebinger16417b42017-03-07 13:48:50 -0800902 int[] subIds = SubscriptionManager.getSubId(mPhoneId);
903 int subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
904 if (subIds != null && subIds.length >= 1) {
905 subId = subIds[0];
906 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700907 return subId;
Brad Ebinger16417b42017-03-07 13:48:50 -0800908 }
909
Pavel Zhamaitsiak9e6eca22015-03-16 15:30:53 -0700910 private static void setWfcModeInternal(Context context, int wfcMode) {
Etan Cohena00c9192014-12-23 15:02:29 -0800911 final ImsManager imsManager = ImsManager.getInstance(context,
912 SubscriptionManager.getDefaultVoicePhoneId());
913 if (imsManager != null) {
914 final int value = wfcMode;
Pavel Zhamaitsiak47aeacf2016-03-30 18:54:55 -0700915 Thread thread = new Thread(new Runnable() {
Etan Cohena00c9192014-12-23 15:02:29 -0800916 public void run() {
917 try {
918 imsManager.getConfigInterface().setProvisionedValue(
919 ImsConfig.ConfigConstants.VOICE_OVER_WIFI_MODE,
920 value);
921 } catch (ImsException e) {
922 // do nothing
923 }
924 }
925 });
Pavel Zhamaitsiak47aeacf2016-03-30 18:54:55 -0700926 thread.start();
Etan Cohena00c9192014-12-23 15:02:29 -0800927 }
928 }
929
Brad Ebinger479f52c2017-08-28 13:19:22 -0700930 private void setWfcModeInternal(int wfcMode) {
Brad Ebinger16417b42017-03-07 13:48:50 -0800931 final int value = wfcMode;
932 Thread thread = new Thread(() -> {
Malcolm Chen201d2312017-09-28 17:28:45 -0700933 try {
934 getConfigInterface().setProvisionedValue(
935 ImsConfig.ConfigConstants.VOICE_OVER_WIFI_MODE, value);
936 } catch (ImsException e) {
937 // do nothing
938 }
Brad Ebinger16417b42017-03-07 13:48:50 -0800939 });
940 thread.start();
941 }
942
Etan Cohena00c9192014-12-23 15:02:29 -0800943 /**
944 * Returns the user configuration of WFC roaming setting
Brad Ebinger16417b42017-03-07 13:48:50 -0800945 *
946 * @deprecated Does not support MSIM devices. Please use
Brad Ebinger479f52c2017-08-28 13:19:22 -0700947 * {@link #isWfcRoamingEnabledByUser()} instead.
Etan Cohena00c9192014-12-23 15:02:29 -0800948 */
949 public static boolean isWfcRoamingEnabledByUser(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700950 ImsManager mgr = ImsManager.getInstance(context,
951 SubscriptionManager.getDefaultVoicePhoneId());
952 if (mgr != null) {
953 return mgr.isWfcRoamingEnabledByUser();
954 }
955 loge("isWfcRoamingEnabledByUser: ImsManager null, returning default value.");
956 return false;
Etan Cohena00c9192014-12-23 15:02:29 -0800957 }
958
959 /**
Malcolm Chen201d2312017-09-28 17:28:45 -0700960 * Returns the user configuration of WFC roaming setting for slot. If not set, it
961 * queries CarrierConfig value as default.
Brad Ebinger16417b42017-03-07 13:48:50 -0800962 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700963 public boolean isWfcRoamingEnabledByUser() {
Malcolm Chen201d2312017-09-28 17:28:45 -0700964 int setting = SubscriptionManager.getIntegerSubscriptionProperty(
965 getSubId(), SubscriptionManager.WFC_IMS_ROAMING_ENABLED,
966 SUB_PROPERTY_NOT_INITIALIZED, mContext);
967 if (setting == SUB_PROPERTY_NOT_INITIALIZED) {
968 return getBooleanCarrierConfig(
969 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_ENABLED_BOOL);
970 } else {
971 return (setting == 1);
972 }
Brad Ebinger16417b42017-03-07 13:48:50 -0800973 }
974
975 /**
Etan Cohena00c9192014-12-23 15:02:29 -0800976 * Change persistent WFC roaming enabled setting
977 */
978 public static void setWfcRoamingSetting(Context context, boolean enabled) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700979 ImsManager mgr = ImsManager.getInstance(context,
Etan Cohena00c9192014-12-23 15:02:29 -0800980 SubscriptionManager.getDefaultVoicePhoneId());
Brad Ebinger479f52c2017-08-28 13:19:22 -0700981 if (mgr != null) {
982 mgr.setWfcRoamingSetting(enabled);
Etan Cohena00c9192014-12-23 15:02:29 -0800983 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700984 loge("setWfcRoamingSetting: ImsManager null, value not set.");
Etan Cohena00c9192014-12-23 15:02:29 -0800985 }
986
987 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800988 * Change persistent WFC roaming enabled setting
989 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700990 public void setWfcRoamingSetting(boolean enabled) {
Malcolm Chen201d2312017-09-28 17:28:45 -0700991 SubscriptionManager.setSubscriptionProperty(getSubId(),
992 SubscriptionManager.WFC_IMS_ROAMING_ENABLED, booleanToPropertyString(enabled)
993 );
Brad Ebinger16417b42017-03-07 13:48:50 -0800994
995 setWfcRoamingSettingInternal(enabled);
996 }
997
998 private void setWfcRoamingSettingInternal(boolean enabled) {
999 final int value = enabled
1000 ? ImsConfig.FeatureValueConstants.ON
1001 : ImsConfig.FeatureValueConstants.OFF;
1002 Thread thread = new Thread(() -> {
Malcolm Chen201d2312017-09-28 17:28:45 -07001003 try {
1004 getConfigInterface().setProvisionedValue(
1005 ImsConfig.ConfigConstants.VOICE_OVER_WIFI_ROAMING, value);
1006 } catch (ImsException e) {
1007 // do nothing
1008 }
Brad Ebinger16417b42017-03-07 13:48:50 -08001009 });
1010 thread.start();
1011 }
1012
1013 /**
Etan Cohena00c9192014-12-23 15:02:29 -08001014 * Returns a platform configuration for WFC which may override the user
1015 * setting. Note: WFC presumes that VoLTE is enabled (these are
1016 * configuration settings which must be done correctly).
Brad Ebinger16417b42017-03-07 13:48:50 -08001017 *
Brad Ebinger479f52c2017-08-28 13:19:22 -07001018 * @deprecated Doesn't work for MSIM devices. Use {@link #isWfcEnabledByPlatform()}
Brad Ebinger16417b42017-03-07 13:48:50 -08001019 * instead.
Etan Cohena00c9192014-12-23 15:02:29 -08001020 */
1021 public static boolean isWfcEnabledByPlatform(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -07001022 ImsManager mgr = ImsManager.getInstance(context,
1023 SubscriptionManager.getDefaultVoicePhoneId());
1024 if (mgr != null) {
1025 return mgr.isWfcEnabledByPlatform();
Etan Cohena00c9192014-12-23 15:02:29 -08001026 }
Brad Ebinger479f52c2017-08-28 13:19:22 -07001027 loge("isWfcEnabledByPlatform: ImsManager null, returning default value.");
1028 return false;
Pavel Zhamaitsiak57911d12015-10-20 14:26:34 -07001029 }
1030
1031 /**
Brad Ebinger16417b42017-03-07 13:48:50 -08001032 * Returns a platform configuration for WFC which may override the user
1033 * setting per slot. Note: WFC presumes that VoLTE is enabled (these are
1034 * configuration settings which must be done correctly).
1035 */
Brad Ebinger479f52c2017-08-28 13:19:22 -07001036 public boolean isWfcEnabledByPlatform() {
Brad Ebinger16417b42017-03-07 13:48:50 -08001037 if (SystemProperties.getInt(PROPERTY_DBG_WFC_AVAIL_OVERRIDE,
1038 PROPERTY_DBG_WFC_AVAIL_OVERRIDE_DEFAULT) == 1) {
1039 return true;
1040 }
1041
1042 return mContext.getResources().getBoolean(
1043 com.android.internal.R.bool.config_device_wfc_ims_available) &&
Brad Ebinger479f52c2017-08-28 13:19:22 -07001044 getBooleanCarrierConfig(
Brad Ebinger16417b42017-03-07 13:48:50 -08001045 CarrierConfigManager.KEY_CARRIER_WFC_IMS_AVAILABLE_BOOL) &&
Brad Ebinger479f52c2017-08-28 13:19:22 -07001046 isGbaValid();
Etan Cohena00c9192014-12-23 15:02:29 -08001047 }
1048
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001049 /**
Brad Ebinger16417b42017-03-07 13:48:50 -08001050 * If carrier requires that IMS is only available if GBA capable SIM is used,
1051 * then this function checks GBA bit in EF IST.
1052 *
1053 * Format of EF IST is defined in 3GPP TS 31.103 (Section 4.2.7).
1054 */
Brad Ebinger479f52c2017-08-28 13:19:22 -07001055 private boolean isGbaValid() {
1056 if (getBooleanCarrierConfig(
Brad Ebinger16417b42017-03-07 13:48:50 -08001057 CarrierConfigManager.KEY_CARRIER_IMS_GBA_REQUIRED_BOOL)) {
Brad Ebinger479f52c2017-08-28 13:19:22 -07001058 final TelephonyManager telephonyManager = new TelephonyManager(mContext, getSubId());
Brad Ebinger16417b42017-03-07 13:48:50 -08001059 String efIst = telephonyManager.getIsimIst();
1060 if (efIst == null) {
Brad Ebinger479f52c2017-08-28 13:19:22 -07001061 loge("isGbaValid - ISF is NULL");
Brad Ebinger16417b42017-03-07 13:48:50 -08001062 return true;
1063 }
1064 boolean result = efIst != null && efIst.length() > 1 &&
1065 (0x02 & (byte)efIst.charAt(1)) != 0;
Brad Ebinger479f52c2017-08-28 13:19:22 -07001066 if (DBG) log("isGbaValid - GBA capable=" + result + ", ISF=" + efIst);
Brad Ebinger16417b42017-03-07 13:48:50 -08001067 return result;
1068 }
1069 return true;
1070 }
1071
1072 /**
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -07001073 * This function should be called when ImsConfig.ACTION_IMS_CONFIG_CHANGED is received.
1074 *
1075 * We cannot register receiver in ImsManager because this would lead to resource leak.
1076 * ImsManager can be created in different processes and it is not notified when that process
1077 * is about to be terminated.
1078 *
1079 * @hide
1080 * */
1081 public static void onProvisionedValueChanged(Context context, int item, String value) {
Amit Mahajan24f7b162016-07-21 16:33:53 -07001082 if (DBG) Rlog.d(TAG, "onProvisionedValueChanged: item=" + item + " val=" + value);
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -07001083 ImsManager mgr = ImsManager.getInstance(context,
1084 SubscriptionManager.getDefaultVoicePhoneId());
1085
1086 switch (item) {
1087 case ImsConfig.ConfigConstants.VLT_SETTING_ENABLED:
Amit Mahajan24f7b162016-07-21 16:33:53 -07001088 mgr.setVolteProvisionedProperty(value.equals("1"));
1089 if (DBG) Rlog.d(TAG,"isVoLteProvisioned = " + mgr.isVolteProvisioned());
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -07001090 break;
1091
1092 case ImsConfig.ConfigConstants.VOICE_OVER_WIFI_SETTING_ENABLED:
Amit Mahajan24f7b162016-07-21 16:33:53 -07001093 mgr.setWfcProvisionedProperty(value.equals("1"));
1094 if (DBG) Rlog.d(TAG,"isWfcProvisioned = " + mgr.isWfcProvisioned());
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -07001095 break;
1096
Nathan Harolda9fc7f12016-06-30 16:12:14 -07001097 case ImsConfig.ConfigConstants.LVC_SETTING_ENABLED:
Amit Mahajan24f7b162016-07-21 16:33:53 -07001098 mgr.setVtProvisionedProperty(value.equals("1"));
1099 if (DBG) Rlog.d(TAG,"isVtProvisioned = " + mgr.isVtProvisioned());
Nathan Harolda9fc7f12016-06-30 16:12:14 -07001100 break;
1101
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -07001102 }
1103 }
1104
Brad Ebingerbe6cb672017-08-25 14:55:00 -07001105 private class AsyncUpdateProvisionedValues extends AsyncTask<Void, Void, Boolean> {
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -07001106 @Override
Brad Ebingerbe6cb672017-08-25 14:55:00 -07001107 protected Boolean doInBackground(Void... params) {
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -07001108 // disable on any error
Amit Mahajan24f7b162016-07-21 16:33:53 -07001109 setVolteProvisionedProperty(false);
1110 setWfcProvisionedProperty(false);
1111 setVtProvisionedProperty(false);
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -07001112
1113 try {
1114 ImsConfig config = getConfigInterface();
1115 if (config != null) {
Amit Mahajan24f7b162016-07-21 16:33:53 -07001116 setVolteProvisionedProperty(getProvisionedBool(config,
1117 ImsConfig.ConfigConstants.VLT_SETTING_ENABLED));
1118 if (DBG) Rlog.d(TAG, "isVoLteProvisioned = " + isVolteProvisioned());
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -07001119
Amit Mahajan24f7b162016-07-21 16:33:53 -07001120 setWfcProvisionedProperty(getProvisionedBool(config,
1121 ImsConfig.ConfigConstants.VOICE_OVER_WIFI_SETTING_ENABLED));
1122 if (DBG) Rlog.d(TAG, "isWfcProvisioned = " + isWfcProvisioned());
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -07001123
Amit Mahajan24f7b162016-07-21 16:33:53 -07001124 setVtProvisionedProperty(getProvisionedBool(config,
1125 ImsConfig.ConfigConstants.LVC_SETTING_ENABLED));
1126 if (DBG) Rlog.d(TAG, "isVtProvisioned = " + isVtProvisioned());
Nathan Harolda9fc7f12016-06-30 16:12:14 -07001127
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -07001128 }
1129 } catch (ImsException ie) {
Meng Wangca7d4c42016-06-30 22:05:24 -07001130 Rlog.e(TAG, "AsyncUpdateProvisionedValues error: ", ie);
Brad Ebingerbe6cb672017-08-25 14:55:00 -07001131 return false;
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -07001132 }
1133
Brad Ebingerbe6cb672017-08-25 14:55:00 -07001134 return true;
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -07001135 }
1136
Brad Ebingerbe6cb672017-08-25 14:55:00 -07001137 @Override
1138 protected void onPostExecute(Boolean completed) {
1139 if (mProvisionBackoff == null) {
1140 return;
1141 }
1142 if (!completed) {
1143 mProvisionBackoff.notifyFailed();
1144 } else {
1145 mProvisionBackoff.stop();
1146 }
1147 }
1148
1149 /**
1150 * Will return with config value or throw an ImsException if we receive an error from
1151 * ImsConfig for that value.
1152 */
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -07001153 private boolean getProvisionedBool(ImsConfig config, int item) throws ImsException {
Brad Ebingerbe6cb672017-08-25 14:55:00 -07001154 int value = config.getProvisionedValue(item);
1155 if (value == ImsConfig.FeatureValueConstants.ERROR) {
1156 throw new ImsException("getProvisionedBool failed with error for item: " + item,
1157 ImsReasonInfo.CODE_LOCAL_INTERNAL_ERROR);
1158 }
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -07001159 return config.getProvisionedValue(item) == ImsConfig.FeatureValueConstants.ON;
1160 }
1161 }
1162
Brad Ebingerbe6cb672017-08-25 14:55:00 -07001163 // used internally only, use #updateProvisionedValues instead.
1164 private void handleUpdateProvisionedValues() {
Brad Ebinger479f52c2017-08-28 13:19:22 -07001165 if (getBooleanCarrierConfig(
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -07001166 CarrierConfigManager.KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL)) {
1167
1168 new AsyncUpdateProvisionedValues().execute();
1169 }
1170 }
1171
1172 /**
Brad Ebingerbe6cb672017-08-25 14:55:00 -07001173 * Asynchronously get VoLTE, WFC, VT provisioning statuses. If ImsConfig is not available, we
1174 * will retry with exponential backoff.
1175 */
1176 private void updateProvisionedValues() {
1177 // Start trying to receive provisioning status after BACKOFF_INITIAL_DELAY_MS.
1178 if (mProvisionBackoff != null) {
1179 mProvisionBackoff.start();
1180 } else {
1181 // bypass and launch async thread once without backoff.
1182 handleUpdateProvisionedValues();
1183 }
1184 }
1185
1186 /**
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001187 * Sync carrier config and user settings with ImsConfig.
1188 *
1189 * @param context for the manager object
1190 * @param phoneId phone id
1191 * @param force update
Brad Ebinger16417b42017-03-07 13:48:50 -08001192 *
Brad Ebinger479f52c2017-08-28 13:19:22 -07001193 * @deprecated Doesn't support MSIM devices. Use {@link #updateImsServiceConfig(boolean)}
1194 * instead.
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001195 */
1196 public static void updateImsServiceConfig(Context context, int phoneId, boolean force) {
Brad Ebinger479f52c2017-08-28 13:19:22 -07001197 ImsManager mgr = ImsManager.getInstance(context, phoneId);
1198 if (mgr != null) {
1199 mgr.updateImsServiceConfig(force);
Pavel Zhamaitsiakfc202992016-03-29 18:07:38 -07001200 }
Brad Ebinger479f52c2017-08-28 13:19:22 -07001201 loge("updateImsServiceConfig: ImsManager null, returning without update.");
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001202 }
1203
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -07001204 /**
Brad Ebinger16417b42017-03-07 13:48:50 -08001205 * Sync carrier config and user settings with ImsConfig.
1206 *
1207 * @param context for the manager object
1208 * @param phoneId phone id
1209 * @param force update
1210 */
Brad Ebinger479f52c2017-08-28 13:19:22 -07001211 public void updateImsServiceConfig(boolean force) {
Brad Ebinger16417b42017-03-07 13:48:50 -08001212 if (!force) {
Brad Ebinger479f52c2017-08-28 13:19:22 -07001213 TelephonyManager tm = new TelephonyManager(mContext, getSubId());
1214 if (tm.getSimState() != TelephonyManager.SIM_STATE_READY) {
1215 log("updateImsServiceConfig: SIM not ready");
Brad Ebinger16417b42017-03-07 13:48:50 -08001216 // Don't disable IMS if SIM is not ready
1217 return;
1218 }
1219 }
1220
1221 if (!mConfigUpdated || force) {
1222 try {
1223 updateProvisionedValues();
1224
1225 // TODO: Extend ImsConfig API and set all feature values in single function call.
1226
1227 // Note: currently the order of updates is set to produce different order of
1228 // setFeatureValue() function calls from setAdvanced4GMode(). This is done to
1229 // differentiate this code path from vendor code perspective.
1230 boolean isImsUsed = updateVolteFeatureValue();
1231 isImsUsed |= updateWfcFeatureAndProvisionedValues();
1232 isImsUsed |= updateVideoCallFeatureValue();
1233
Brad Ebinger479f52c2017-08-28 13:19:22 -07001234 if (isImsUsed || !isTurnOffImsAllowedByPlatform()) {
Brad Ebinger16417b42017-03-07 13:48:50 -08001235 // Turn on IMS if it is used.
1236 // Also, if turning off is not allowed for current carrier,
1237 // we need to turn IMS on because it might be turned off before
1238 // phone switched to current carrier.
Brad Ebinger479f52c2017-08-28 13:19:22 -07001239 log("updateImsServiceConfig: turnOnIms");
Brad Ebinger16417b42017-03-07 13:48:50 -08001240 turnOnIms();
1241 } else {
1242 // Turn off IMS if it is not used AND turning off is allowed for carrier.
Brad Ebinger479f52c2017-08-28 13:19:22 -07001243 log("updateImsServiceConfig: turnOffIms");
Brad Ebinger16417b42017-03-07 13:48:50 -08001244 turnOffIms();
1245 }
1246
1247 mConfigUpdated = true;
1248 } catch (ImsException e) {
Brad Ebinger479f52c2017-08-28 13:19:22 -07001249 loge("updateImsServiceConfig: ", e);
Brad Ebinger16417b42017-03-07 13:48:50 -08001250 mConfigUpdated = false;
1251 }
1252 }
1253 }
1254
1255 /**
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -07001256 * Update VoLTE config
1257 * @return whether feature is On
1258 * @throws ImsException
1259 */
1260 private boolean updateVolteFeatureValue() throws ImsException {
Brad Ebinger479f52c2017-08-28 13:19:22 -07001261 boolean available = isVolteEnabledByPlatform();
1262 boolean enabled = isEnhanced4gLteModeSettingEnabledByUser();
1263 boolean isNonTty = isNonTtyOrTtyOnVolteEnabled();
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -08001264 boolean isFeatureOn = available && enabled && isNonTty;
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001265
1266 log("updateVolteFeatureValue: available = " + available
1267 + ", enabled = " + enabled
1268 + ", nonTTY = " + isNonTty);
1269
1270 getConfigInterface().setFeatureValue(
1271 ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_LTE,
1272 TelephonyManager.NETWORK_TYPE_LTE,
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -08001273 isFeatureOn ?
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001274 ImsConfig.FeatureValueConstants.ON :
1275 ImsConfig.FeatureValueConstants.OFF,
Pavel Zhamaitsiakf4b90322016-01-26 14:34:09 -08001276 mImsConfigListener);
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -07001277
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -08001278 return isFeatureOn;
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001279 }
1280
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -07001281 /**
Jack Yu643ffe42016-07-08 14:25:46 -07001282 * Update video call over LTE config
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -07001283 * @return whether feature is On
1284 * @throws ImsException
1285 */
1286 private boolean updateVideoCallFeatureValue() throws ImsException {
Brad Ebinger479f52c2017-08-28 13:19:22 -07001287 boolean available = isVtEnabledByPlatform();
1288 boolean enabled = isVtEnabledByUser();
1289 boolean isNonTty = isNonTtyOrTtyOnVolteEnabled();
Amit Mahajan24f7b162016-07-21 16:33:53 -07001290 boolean isDataEnabled = isDataEnabled();
Brad Ebinger479f52c2017-08-28 13:19:22 -07001291 boolean ignoreDataEnabledChanged = getBooleanCarrierConfig(
Jack Yu57781852016-11-16 17:20:38 -08001292 CarrierConfigManager.KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS);
Jack Yu643ffe42016-07-08 14:25:46 -07001293
Jack Yu57781852016-11-16 17:20:38 -08001294 boolean isFeatureOn = available && enabled && isNonTty
1295 && (ignoreDataEnabledChanged || isDataEnabled);
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001296
1297 log("updateVideoCallFeatureValue: available = " + available
1298 + ", enabled = " + enabled
Jack Yu643ffe42016-07-08 14:25:46 -07001299 + ", nonTTY = " + isNonTty
Amit Mahajan24f7b162016-07-21 16:33:53 -07001300 + ", data enabled = " + isDataEnabled);
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001301
1302 getConfigInterface().setFeatureValue(
1303 ImsConfig.FeatureConstants.FEATURE_TYPE_VIDEO_OVER_LTE,
1304 TelephonyManager.NETWORK_TYPE_LTE,
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -08001305 isFeatureOn ?
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001306 ImsConfig.FeatureValueConstants.ON :
1307 ImsConfig.FeatureValueConstants.OFF,
Pavel Zhamaitsiakf4b90322016-01-26 14:34:09 -08001308 mImsConfigListener);
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -07001309
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -08001310 return isFeatureOn;
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001311 }
1312
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -07001313 /**
1314 * Update WFC config
1315 * @return whether feature is On
1316 * @throws ImsException
1317 */
1318 private boolean updateWfcFeatureAndProvisionedValues() throws ImsException {
Brad Ebinger479f52c2017-08-28 13:19:22 -07001319 TelephonyManager tm = new TelephonyManager(mContext, getSubId());
1320 boolean isNetworkRoaming = tm.isNetworkRoaming();
1321 boolean available = isWfcEnabledByPlatform();
1322 boolean enabled = isWfcEnabledByUser();
Suresh Koleti76491082017-04-21 18:39:50 +05301323 updateDefaultWfcMode();
Brad Ebinger479f52c2017-08-28 13:19:22 -07001324 int mode = getWfcMode(isNetworkRoaming);
1325 boolean roaming = isWfcRoamingEnabledByUser();
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -08001326 boolean isFeatureOn = available && enabled;
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001327
1328 log("updateWfcFeatureAndProvisionedValues: available = " + available
1329 + ", enabled = " + enabled
1330 + ", mode = " + mode
1331 + ", roaming = " + roaming);
1332
1333 getConfigInterface().setFeatureValue(
Pavel Zhamaitsiake6f99432015-09-11 10:29:30 -07001334 ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_WIFI,
1335 TelephonyManager.NETWORK_TYPE_IWLAN,
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -08001336 isFeatureOn ?
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001337 ImsConfig.FeatureValueConstants.ON :
1338 ImsConfig.FeatureValueConstants.OFF,
Pavel Zhamaitsiakf4b90322016-01-26 14:34:09 -08001339 mImsConfigListener);
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001340
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -08001341 if (!isFeatureOn) {
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001342 mode = ImsConfig.WfcModeFeatureValueConstants.CELLULAR_PREFERRED;
1343 roaming = false;
1344 }
1345 setWfcModeInternal(mContext, mode);
Brad Ebinger16417b42017-03-07 13:48:50 -08001346 setWfcRoamingSettingInternal(roaming);
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -07001347
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -08001348 return isFeatureOn;
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001349 }
1350
Brad Ebinger16780ff2017-01-26 11:18:21 -08001351 /**
Brad Ebinger479f52c2017-08-28 13:19:22 -07001352 * Do NOT use this directly, instead use {@link #getInstance(Context, int)}.
Brad Ebinger16780ff2017-01-26 11:18:21 -08001353 */
1354 @VisibleForTesting
1355 public ImsManager(Context context, int phoneId) {
Wink Savilleef36ef62014-06-11 08:39:38 -07001356 mContext = context;
Etan Cohenabbd7882014-09-26 22:35:35 -07001357 mPhoneId = phoneId;
Brad Ebinger16780ff2017-01-26 11:18:21 -08001358 mConfigDynamicBind = mContext.getResources().getBoolean(
1359 com.android.internal.R.bool.config_dynamic_bind_ims);
Brad Ebinger16417b42017-03-07 13:48:50 -08001360 mConfigManager = (CarrierConfigManager) context.getSystemService(
1361 Context.CARRIER_CONFIG_SERVICE);
Brad Ebingerbe6cb672017-08-25 14:55:00 -07001362 if (Looper.getMainLooper() != null) {
1363 mProvisionBackoff = new ExponentialBackoff(BACKOFF_INITIAL_DELAY_MS,
1364 BACKOFF_MAX_DELAY_MS, BACKOFF_MULTIPLIER,
1365 new Handler(Looper.getMainLooper()), this::handleUpdateProvisionedValues);
1366 }
Brad Ebinger16780ff2017-01-26 11:18:21 -08001367 createImsService();
1368 }
1369
1370 /**
Brad Ebinger16780ff2017-01-26 11:18:21 -08001371 * @return Whether or not ImsManager is configured to Dynamically bind or not to support legacy
1372 * devices.
1373 */
1374 public boolean isDynamicBinding() {
1375 return mConfigDynamicBind;
Wink Savilleef36ef62014-06-11 08:39:38 -07001376 }
1377
Etan Cohenf4311122015-02-26 17:47:13 -08001378 /*
Brad Ebingerff097922017-06-19 15:43:08 -07001379 * Returns a flag indicating whether the IMS service is available. If it is not available,
1380 * it will try to connect before reporting failure.
Etan Cohenf4311122015-02-26 17:47:13 -08001381 */
1382 public boolean isServiceAvailable() {
Brad Ebingerff097922017-06-19 15:43:08 -07001383 connectIfServiceIsAvailable();
Brad Ebinger16780ff2017-01-26 11:18:21 -08001384 // mImsServiceProxy will always create an ImsServiceProxy.
1385 return mImsServiceProxy.isBinderAlive();
Etan Cohenf4311122015-02-26 17:47:13 -08001386 }
1387
Suresh Koleticc3139c2017-11-03 18:23:57 +05301388 /*
1389 * Returns a flag indicating whether the IMS service is ready to send requests to lower layers.
1390 */
1391 public boolean isServiceReady() {
1392 connectIfServiceIsAvailable();
1393 return mImsServiceProxy.isBinderReady();
1394 }
1395
Brad Ebingerff097922017-06-19 15:43:08 -07001396 /**
1397 * If the service is available, try to reconnect.
1398 */
1399 public void connectIfServiceIsAvailable() {
1400 if (mImsServiceProxy == null || !mImsServiceProxy.isBinderAlive()) {
1401 createImsService();
1402 }
1403 }
1404
Pavel Zhamaitsiakf4b90322016-01-26 14:34:09 -08001405 public void setImsConfigListener(ImsConfigListener listener) {
1406 mImsConfigListener = listener;
1407 }
1408
Brad Ebingerb10b61e2017-04-18 11:45:26 -07001409
1410 /**
1411 * Adds a callback for status changed events if the binder is already available. If it is not,
1412 * this method will throw an ImsException.
1413 */
Brad Ebinger0e170c72017-12-14 14:24:02 -08001414 public void addNotifyStatusChangedCallbackIfAvailable(ImsServiceProxy.IFeatureUpdate c)
Brad Ebingerb10b61e2017-04-18 11:45:26 -07001415 throws ImsException {
1416 if (!mImsServiceProxy.isBinderAlive()) {
1417 throw new ImsException("Binder is not active!",
1418 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1419 }
Brad Ebinger16780ff2017-01-26 11:18:21 -08001420 if (c != null) {
1421 mStatusCallbacks.add(c);
1422 }
1423 }
1424
Brad Ebinger0e170c72017-12-14 14:24:02 -08001425 public void removeNotifyStatusChangedCallback(ImsServiceProxy.IFeatureUpdate c) {
1426 if (c != null) {
1427 mStatusCallbacks.remove(c);
1428 } else {
1429 Log.w(TAG, "removeNotifyStatusChangedCallback: callback is null!");
1430 }
1431 }
1432
Wink Savilleef36ef62014-06-11 08:39:38 -07001433 /**
1434 * Opens the IMS service for making calls and/or receiving generic IMS calls.
1435 * The caller may make subsquent calls through {@link #makeCall}.
1436 * The IMS service will register the device to the operator's network with the credentials
1437 * (from ISIM) periodically in order to receive calls from the operator's network.
1438 * When the IMS service receives a new call, it will send out an intent with
1439 * the provided action string.
1440 * The intent contains a call ID extra {@link getCallId} and it can be used to take a call.
1441 *
1442 * @param serviceClass a service class specified in {@link ImsServiceClass}
1443 * For VoLTE service, it MUST be a {@link ImsServiceClass#MMTEL}.
1444 * @param incomingCallPendingIntent When an incoming call is received,
1445 * the IMS service will call {@link PendingIntent#send(Context, int, Intent)} to
1446 * send back the intent to the caller with {@link #INCOMING_CALL_RESULT_CODE}
1447 * as the result code and the intent to fill in the call ID; It cannot be null
1448 * @param listener To listen to IMS registration events; It cannot be null
1449 * @return identifier (greater than 0) for the specified service
1450 * @throws NullPointerException if {@code incomingCallPendingIntent}
1451 * or {@code listener} is null
1452 * @throws ImsException if calling the IMS service results in an error
1453 * @see #getCallId
Brad Ebinger16780ff2017-01-26 11:18:21 -08001454 * @see #getImsSessionId
Wink Savilleef36ef62014-06-11 08:39:38 -07001455 */
1456 public int open(int serviceClass, PendingIntent incomingCallPendingIntent,
1457 ImsConnectionStateListener listener) throws ImsException {
1458 checkAndThrowExceptionIfServiceUnavailable();
1459
1460 if (incomingCallPendingIntent == null) {
1461 throw new NullPointerException("incomingCallPendingIntent can't be null");
1462 }
1463
1464 if (listener == null) {
1465 throw new NullPointerException("listener can't be null");
1466 }
1467
1468 int result = 0;
1469
1470 try {
Brad Ebinger57b11892017-06-13 16:21:35 -07001471 // Register a stub implementation of the ImsRegistrationListener. There is the
1472 // possibility that if we use the real implementation of the ImsRegistrationListener,
1473 // it will be added twice.
1474 // TODO: Remove ImsRegistrationListener from startSession API (b/62588776)
Brad Ebinger16780ff2017-01-26 11:18:21 -08001475 result = mImsServiceProxy.startSession(incomingCallPendingIntent,
Brad Ebinger57b11892017-06-13 16:21:35 -07001476 new ImsRegistrationListenerBase());
1477 addRegistrationListener(listener);
1478 log("open: Session started and registration listener added.");
Wink Savilleef36ef62014-06-11 08:39:38 -07001479 } catch (RemoteException e) {
1480 throw new ImsException("open()", e,
1481 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1482 }
1483
1484 if (result <= 0) {
1485 // If the return value is a minus value,
1486 // it means that an error occurred in the service.
1487 // So, it needs to convert to the reason code specified in ImsReasonInfo.
1488 throw new ImsException("open()", (result * (-1)));
1489 }
1490
1491 return result;
1492 }
1493
1494 /**
Pavel Zhamaitsiakce410172016-04-15 10:55:56 -07001495 * Adds registration listener to the IMS service.
1496 *
1497 * @param serviceClass a service class specified in {@link ImsServiceClass}
1498 * For VoLTE service, it MUST be a {@link ImsServiceClass#MMTEL}.
1499 * @param listener To listen to IMS registration events; It cannot be null
1500 * @throws NullPointerException if {@code listener} is null
1501 * @throws ImsException if calling the IMS service results in an error
Brad Ebinger9a0280c2017-06-01 15:58:48 -07001502 *
1503 * @deprecated Use {@link #addRegistrationListener(ImsConnectionStateListener)} instead.
Pavel Zhamaitsiakce410172016-04-15 10:55:56 -07001504 */
1505 public void addRegistrationListener(int serviceClass, ImsConnectionStateListener listener)
1506 throws ImsException {
Brad Ebinger9a0280c2017-06-01 15:58:48 -07001507 addRegistrationListener(listener);
1508 }
1509
1510 /**
1511 * Adds registration listener to the IMS service.
1512 *
1513 * @param listener To listen to IMS registration events; It cannot be null
1514 * @throws NullPointerException if {@code listener} is null
1515 * @throws ImsException if calling the IMS service results in an error
1516 */
Brad Ebinger0e170c72017-12-14 14:24:02 -08001517 public void addRegistrationListener(ImsConnectionStateListener listener) throws ImsException {
Pavel Zhamaitsiakce410172016-04-15 10:55:56 -07001518 if (listener == null) {
1519 throw new NullPointerException("listener can't be null");
1520 }
Brad Ebinger57b11892017-06-13 16:21:35 -07001521 // We only want this Proxy registered once.
Brad Ebinger9a0280c2017-06-01 15:58:48 -07001522 synchronized (mHasRegisteredLock) {
1523 if (!mHasRegisteredForProxy) {
1524 try {
Brad Ebinger57b11892017-06-13 16:21:35 -07001525 checkAndThrowExceptionIfServiceUnavailable();
Brad Ebinger0e170c72017-12-14 14:24:02 -08001526 // TODO: Remove once new MmTelFeature is merged in
1527 mImsServiceProxy.addRegistrationListener(mImsRegistrationListenerProxy);
Brad Ebinger3418c132018-01-18 12:03:33 -08001528 IImsRegistration regBinder = mImsServiceProxy.getRegistration();
1529 if (regBinder != null) {
1530 regBinder.addRegistrationCallback(mRegistrationCallback);
1531 }
Brad Ebinger0e170c72017-12-14 14:24:02 -08001532 log("Registration Callback/Listener registered.");
Brad Ebinger9a0280c2017-06-01 15:58:48 -07001533 // Only record if there isn't a RemoteException.
1534 mHasRegisteredForProxy = true;
1535 } catch (RemoteException e) {
1536 throw new ImsException("addRegistrationListener()", e,
1537 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1538 }
1539 }
1540 }
1541 synchronized (mRegistrationListeners) {
Brad Ebinger57b11892017-06-13 16:21:35 -07001542 log("Local registration listener added: " + listener);
Brad Ebinger9a0280c2017-06-01 15:58:48 -07001543 mRegistrationListeners.add(listener);
Pavel Zhamaitsiakce410172016-04-15 10:55:56 -07001544 }
1545 }
1546
1547 /**
Brad Ebinger16780ff2017-01-26 11:18:21 -08001548 * Removes the registration listener from the IMS service.
1549 *
Brad Ebinger16780ff2017-01-26 11:18:21 -08001550 * @param listener Previously registered listener that will be removed. Can not be null.
1551 * @throws NullPointerException if {@code listener} is null
1552 * @throws ImsException if calling the IMS service results in an error
1553 * instead.
1554 */
Brad Ebingerb5f30c72017-02-17 14:54:31 -08001555 public void removeRegistrationListener(ImsConnectionStateListener listener)
Brad Ebinger16780ff2017-01-26 11:18:21 -08001556 throws ImsException {
Brad Ebinger16780ff2017-01-26 11:18:21 -08001557 if (listener == null) {
1558 throw new NullPointerException("listener can't be null");
1559 }
1560
Brad Ebinger9a0280c2017-06-01 15:58:48 -07001561 synchronized (mRegistrationListeners) {
Brad Ebinger57b11892017-06-13 16:21:35 -07001562 log("Local registration listener removed: " + listener);
Brad Ebinger9a0280c2017-06-01 15:58:48 -07001563 mRegistrationListeners.remove(listener);
Brad Ebinger16780ff2017-01-26 11:18:21 -08001564 }
1565 }
1566
1567 /**
Wink Savilleef36ef62014-06-11 08:39:38 -07001568 * Closes the specified service ({@link ImsServiceClass}) not to make/receive calls.
1569 * All the resources that were allocated to the service are also released.
1570 *
Brad Ebinger16780ff2017-01-26 11:18:21 -08001571 * @param sessionId a session id to be closed which is obtained from {@link ImsManager#open}
Wink Savilleef36ef62014-06-11 08:39:38 -07001572 * @throws ImsException if calling the IMS service results in an error
1573 */
Brad Ebinger16780ff2017-01-26 11:18:21 -08001574 public void close(int sessionId) throws ImsException {
Wink Savilleef36ef62014-06-11 08:39:38 -07001575 checkAndThrowExceptionIfServiceUnavailable();
1576
1577 try {
Brad Ebinger16780ff2017-01-26 11:18:21 -08001578 mImsServiceProxy.endSession(sessionId);
Wink Savilleef36ef62014-06-11 08:39:38 -07001579 } catch (RemoteException e) {
1580 throw new ImsException("close()", e,
1581 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1582 } finally {
1583 mUt = null;
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -05001584 mConfig = null;
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -07001585 mEcbm = null;
Tyler Gunn4d128b62016-04-13 15:44:38 -07001586 mMultiEndpoint = null;
Wink Savilleef36ef62014-06-11 08:39:38 -07001587 }
1588 }
1589
1590 /**
1591 * Gets the configuration interface to provision / withdraw the supplementary service settings.
1592 *
Wink Savilleef36ef62014-06-11 08:39:38 -07001593 * @return the Ut interface instance
1594 * @throws ImsException if getting the Ut interface results in an error
1595 */
Brad Ebingerb5f30c72017-02-17 14:54:31 -08001596 public ImsUtInterface getSupplementaryServiceConfiguration()
Wink Savilleef36ef62014-06-11 08:39:38 -07001597 throws ImsException {
Brad Ebinger16780ff2017-01-26 11:18:21 -08001598 // FIXME: manage the multiple Ut interfaces based on the session id
Brad Ebinger138b4a62017-06-20 16:29:50 -07001599 if (mUt != null && mUt.isBinderAlive()) {
1600 return mUt;
Wink Savilleef36ef62014-06-11 08:39:38 -07001601 }
1602
Brad Ebinger138b4a62017-06-20 16:29:50 -07001603 checkAndThrowExceptionIfServiceUnavailable();
1604 try {
1605 IImsUt iUt = mImsServiceProxy.getUtInterface();
1606
1607 if (iUt == null) {
1608 throw new ImsException("getSupplementaryServiceConfiguration()",
1609 ImsReasonInfo.CODE_UT_NOT_SUPPORTED);
1610 }
1611
1612 mUt = new ImsUt(iUt);
1613 } catch (RemoteException e) {
1614 throw new ImsException("getSupplementaryServiceConfiguration()", e,
1615 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1616 }
Wink Savilleef36ef62014-06-11 08:39:38 -07001617 return mUt;
1618 }
1619
1620 /**
1621 * Checks if the IMS service has successfully registered to the IMS network
1622 * with the specified service & call type.
1623 *
Wink Savilleef36ef62014-06-11 08:39:38 -07001624 * @param serviceType a service type that is specified in {@link ImsCallProfile}
1625 * {@link ImsCallProfile#SERVICE_TYPE_NORMAL}
1626 * {@link ImsCallProfile#SERVICE_TYPE_EMERGENCY}
1627 * @param callType a call type that is specified in {@link ImsCallProfile}
1628 * {@link ImsCallProfile#CALL_TYPE_VOICE_N_VIDEO}
1629 * {@link ImsCallProfile#CALL_TYPE_VOICE}
1630 * {@link ImsCallProfile#CALL_TYPE_VT}
1631 * {@link ImsCallProfile#CALL_TYPE_VS}
1632 * @return true if the specified service id is connected to the IMS network;
1633 * false otherwise
1634 * @throws ImsException if calling the IMS service results in an error
1635 */
Brad Ebingerb5f30c72017-02-17 14:54:31 -08001636 public boolean isConnected(int serviceType, int callType)
Wink Savilleef36ef62014-06-11 08:39:38 -07001637 throws ImsException {
1638 checkAndThrowExceptionIfServiceUnavailable();
1639
1640 try {
Brad Ebingerb5f30c72017-02-17 14:54:31 -08001641 return mImsServiceProxy.isConnected(serviceType, callType);
Wink Savilleef36ef62014-06-11 08:39:38 -07001642 } catch (RemoteException e) {
1643 throw new ImsException("isServiceConnected()", e,
1644 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1645 }
1646 }
1647
1648 /**
1649 * Checks if the specified IMS service is opend.
1650 *
Wink Savilleef36ef62014-06-11 08:39:38 -07001651 * @return true if the specified service id is opened; false otherwise
1652 * @throws ImsException if calling the IMS service results in an error
1653 */
Brad Ebingerb5f30c72017-02-17 14:54:31 -08001654 public boolean isOpened() throws ImsException {
Wink Savilleef36ef62014-06-11 08:39:38 -07001655 checkAndThrowExceptionIfServiceUnavailable();
1656
1657 try {
Brad Ebingerb5f30c72017-02-17 14:54:31 -08001658 return mImsServiceProxy.isOpened();
Wink Savilleef36ef62014-06-11 08:39:38 -07001659 } catch (RemoteException e) {
1660 throw new ImsException("isOpened()", e,
1661 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1662 }
1663 }
1664
1665 /**
1666 * Creates a {@link ImsCallProfile} from the service capabilities & IMS registration state.
1667 *
Brad Ebinger16780ff2017-01-26 11:18:21 -08001668 * @param sessionId a session id which is obtained from {@link ImsManager#open}
Wink Savilleef36ef62014-06-11 08:39:38 -07001669 * @param serviceType a service type that is specified in {@link ImsCallProfile}
1670 * {@link ImsCallProfile#SERVICE_TYPE_NONE}
1671 * {@link ImsCallProfile#SERVICE_TYPE_NORMAL}
1672 * {@link ImsCallProfile#SERVICE_TYPE_EMERGENCY}
1673 * @param callType a call type that is specified in {@link ImsCallProfile}
1674 * {@link ImsCallProfile#CALL_TYPE_VOICE}
1675 * {@link ImsCallProfile#CALL_TYPE_VT}
1676 * {@link ImsCallProfile#CALL_TYPE_VT_TX}
1677 * {@link ImsCallProfile#CALL_TYPE_VT_RX}
1678 * {@link ImsCallProfile#CALL_TYPE_VT_NODIR}
1679 * {@link ImsCallProfile#CALL_TYPE_VS}
1680 * {@link ImsCallProfile#CALL_TYPE_VS_TX}
1681 * {@link ImsCallProfile#CALL_TYPE_VS_RX}
1682 * @return a {@link ImsCallProfile} object
1683 * @throws ImsException if calling the IMS service results in an error
1684 */
Brad Ebingerb5f30c72017-02-17 14:54:31 -08001685 public ImsCallProfile createCallProfile(int sessionId, int serviceType, int callType)
1686 throws ImsException {
Wink Savilleef36ef62014-06-11 08:39:38 -07001687 checkAndThrowExceptionIfServiceUnavailable();
1688
1689 try {
Brad Ebinger16780ff2017-01-26 11:18:21 -08001690 return mImsServiceProxy.createCallProfile(sessionId, serviceType, callType);
Wink Savilleef36ef62014-06-11 08:39:38 -07001691 } catch (RemoteException e) {
1692 throw new ImsException("createCallProfile()", e,
1693 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1694 }
1695 }
1696
1697 /**
1698 * Creates a {@link ImsCall} to make a call.
1699 *
Brad Ebinger16780ff2017-01-26 11:18:21 -08001700 * @param sessionId a session id which is obtained from {@link ImsManager#open}
Wink Savilleef36ef62014-06-11 08:39:38 -07001701 * @param profile a call profile to make the call
1702 * (it contains service type, call type, media information, etc.)
1703 * @param participants participants to invite the conference call
1704 * @param listener listen to the call events from {@link ImsCall}
1705 * @return a {@link ImsCall} object
1706 * @throws ImsException if calling the IMS service results in an error
1707 */
Brad Ebinger16780ff2017-01-26 11:18:21 -08001708 public ImsCall makeCall(int sessionId, ImsCallProfile profile, String[] callees,
Wink Savilleef36ef62014-06-11 08:39:38 -07001709 ImsCall.Listener listener) throws ImsException {
1710 if (DBG) {
Brad Ebinger16780ff2017-01-26 11:18:21 -08001711 log("makeCall :: sessionId=" + sessionId
fionaxu7b3107c2016-07-06 14:04:06 -07001712 + ", profile=" + profile);
Wink Savilleef36ef62014-06-11 08:39:38 -07001713 }
1714
1715 checkAndThrowExceptionIfServiceUnavailable();
1716
1717 ImsCall call = new ImsCall(mContext, profile);
1718
1719 call.setListener(listener);
Brad Ebinger16780ff2017-01-26 11:18:21 -08001720 ImsCallSession session = createCallSession(sessionId, profile);
Wink Savilleef36ef62014-06-11 08:39:38 -07001721
1722 if ((callees != null) && (callees.length == 1)) {
1723 call.start(session, callees[0]);
1724 } else {
1725 call.start(session, callees);
1726 }
1727
1728 return call;
1729 }
1730
1731 /**
1732 * Creates a {@link ImsCall} to take an incoming call.
1733 *
Brad Ebinger16780ff2017-01-26 11:18:21 -08001734 * @param sessionId a session id which is obtained from {@link ImsManager#open}
Wink Savilleef36ef62014-06-11 08:39:38 -07001735 * @param incomingCallIntent the incoming call broadcast intent
1736 * @param listener to listen to the call events from {@link ImsCall}
1737 * @return a {@link ImsCall} object
1738 * @throws ImsException if calling the IMS service results in an error
1739 */
Brad Ebinger16780ff2017-01-26 11:18:21 -08001740 public ImsCall takeCall(int sessionId, Intent incomingCallIntent,
Wink Savilleef36ef62014-06-11 08:39:38 -07001741 ImsCall.Listener listener) throws ImsException {
1742 if (DBG) {
Brad Ebinger16780ff2017-01-26 11:18:21 -08001743 log("takeCall :: sessionId=" + sessionId
Wink Savilleef36ef62014-06-11 08:39:38 -07001744 + ", incomingCall=" + incomingCallIntent);
1745 }
1746
1747 checkAndThrowExceptionIfServiceUnavailable();
1748
1749 if (incomingCallIntent == null) {
1750 throw new ImsException("Can't retrieve session with null intent",
1751 ImsReasonInfo.CODE_LOCAL_ILLEGAL_ARGUMENT);
1752 }
1753
Brad Ebinger16780ff2017-01-26 11:18:21 -08001754 int incomingServiceId = getImsSessionId(incomingCallIntent);
Wink Savilleef36ef62014-06-11 08:39:38 -07001755
Brad Ebinger16780ff2017-01-26 11:18:21 -08001756 if (sessionId != incomingServiceId) {
Wink Savilleef36ef62014-06-11 08:39:38 -07001757 throw new ImsException("Service id is mismatched in the incoming call intent",
1758 ImsReasonInfo.CODE_LOCAL_ILLEGAL_ARGUMENT);
1759 }
1760
1761 String callId = getCallId(incomingCallIntent);
1762
1763 if (callId == null) {
1764 throw new ImsException("Call ID missing in the incoming call intent",
1765 ImsReasonInfo.CODE_LOCAL_ILLEGAL_ARGUMENT);
1766 }
1767
1768 try {
Brad Ebinger16780ff2017-01-26 11:18:21 -08001769 IImsCallSession session = mImsServiceProxy.getPendingCallSession(sessionId, callId);
Wink Savilleef36ef62014-06-11 08:39:38 -07001770
1771 if (session == null) {
1772 throw new ImsException("No pending session for the call",
1773 ImsReasonInfo.CODE_LOCAL_NO_PENDING_CALL);
1774 }
1775
1776 ImsCall call = new ImsCall(mContext, session.getCallProfile());
1777
1778 call.attachSession(new ImsCallSession(session));
1779 call.setListener(listener);
1780
1781 return call;
1782 } catch (Throwable t) {
1783 throw new ImsException("takeCall()", t, ImsReasonInfo.CODE_UNSPECIFIED);
1784 }
1785 }
1786
1787 /**
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -05001788 * Gets the config interface to get/set service/capability parameters.
1789 *
1790 * @return the ImsConfig instance.
1791 * @throws ImsException if getting the setting interface results in an error.
1792 */
1793 public ImsConfig getConfigInterface() throws ImsException {
Brad Ebinger138b4a62017-06-20 16:29:50 -07001794 if (mConfig != null && mConfig.isBinderAlive()) {
1795 return mConfig;
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -05001796 }
Brad Ebinger138b4a62017-06-20 16:29:50 -07001797
1798 checkAndThrowExceptionIfServiceUnavailable();
1799 try {
1800 IImsConfig config = mImsServiceProxy.getConfigInterface();
1801 if (config == null) {
1802 throw new ImsException("getConfigInterface()",
1803 ImsReasonInfo.CODE_LOCAL_SERVICE_UNAVAILABLE);
1804 }
1805 mConfig = new ImsConfig(config, mContext);
1806 } catch (RemoteException e) {
1807 throw new ImsException("getConfigInterface()", e,
1808 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1809 }
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -05001810 return mConfig;
1811 }
1812
Hall Liue511a202017-08-17 15:49:58 -07001813 /**
1814 * Set the TTY mode. This is the actual tty mode (varies depending on peripheral status)
1815 */
1816 public void setTtyMode(int ttyMode) throws ImsException {
Brad Ebinger479f52c2017-08-28 13:19:22 -07001817 if (!getBooleanCarrierConfig(
Hall Liue511a202017-08-17 15:49:58 -07001818 CarrierConfigManager.KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL)) {
1819 setAdvanced4GMode((ttyMode == TelecomManager.TTY_MODE_OFF) &&
Brad Ebinger479f52c2017-08-28 13:19:22 -07001820 isEnhanced4gLteModeSettingEnabledByUser());
Hall Liue511a202017-08-17 15:49:58 -07001821 }
1822 }
1823
1824 /**
1825 * Sets the UI TTY mode. This is the preferred TTY mode that the user sets in the call
1826 * settings screen.
1827 */
Brad Ebingerb5f30c72017-02-17 14:54:31 -08001828 public void setUiTTYMode(Context context, int uiTtyMode, Message onComplete)
Shriram Ganeshc403b7b2014-08-14 14:18:57 +05301829 throws ImsException {
1830
Etan Cohen82f78122014-12-15 10:10:14 -08001831 checkAndThrowExceptionIfServiceUnavailable();
Shriram Ganeshc403b7b2014-08-14 14:18:57 +05301832
Etan Cohen82f78122014-12-15 10:10:14 -08001833 try {
Brad Ebingerb5f30c72017-02-17 14:54:31 -08001834 mImsServiceProxy.setUiTTYMode(uiTtyMode, onComplete);
Etan Cohen82f78122014-12-15 10:10:14 -08001835 } catch (RemoteException e) {
1836 throw new ImsException("setTTYMode()", e,
1837 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1838 }
Shriram Ganeshc403b7b2014-08-14 14:18:57 +05301839 }
1840
Naveen Kalla525c3a22017-02-06 14:46:42 -08001841 private ImsReasonInfo makeACopy(ImsReasonInfo imsReasonInfo) {
1842 Parcel p = Parcel.obtain();
1843 imsReasonInfo.writeToParcel(p, 0);
1844 p.setDataPosition(0);
1845 ImsReasonInfo clonedReasonInfo = ImsReasonInfo.CREATOR.createFromParcel(p);
1846 p.recycle();
1847 return clonedReasonInfo;
1848 }
1849
1850 /**
1851 * Get Recent IMS Disconnect Reasons.
1852 *
1853 * @return ArrayList of ImsReasonInfo objects. MAX size of the arraylist
1854 * is MAX_RECENT_DISCONNECT_REASONS. The objects are in the
1855 * chronological order.
1856 */
1857 public ArrayList<ImsReasonInfo> getRecentImsDisconnectReasons() {
1858 ArrayList<ImsReasonInfo> disconnectReasons = new ArrayList<>();
1859
1860 for (ImsReasonInfo reason : mRecentDisconnectReasons) {
1861 disconnectReasons.add(makeACopy(reason));
1862 }
1863 return disconnectReasons;
1864 }
Brad Ebinger16417b42017-03-07 13:48:50 -08001865
Brad Ebinger16780ff2017-01-26 11:18:21 -08001866 public int getImsServiceStatus() throws ImsException {
Brad Ebinger16780ff2017-01-26 11:18:21 -08001867 return mImsServiceProxy.getFeatureStatus();
1868 }
Naveen Kalla525c3a22017-02-06 14:46:42 -08001869
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -05001870 /**
Junda Liue7663c02015-06-23 11:16:26 -07001871 * Get the boolean config from carrier config manager.
1872 *
Brad Ebinger16417b42017-03-07 13:48:50 -08001873 * @param key config key defined in CarrierConfigManager
1874 * @return boolean value of corresponding key.
1875 */
Brad Ebinger479f52c2017-08-28 13:19:22 -07001876 private boolean getBooleanCarrierConfig(String key) {
Brad Ebinger16417b42017-03-07 13:48:50 -08001877 int[] subIds = SubscriptionManager.getSubId(mPhoneId);
1878 int subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1879 if (subIds != null && subIds.length >= 1) {
1880 subId = subIds[0];
1881 }
1882 PersistableBundle b = null;
1883 if (mConfigManager != null) {
1884 // If an invalid subId is used, this bundle will contain default values.
1885 b = mConfigManager.getConfigForSubId(subId);
1886 }
1887 if (b != null) {
1888 return b.getBoolean(key);
1889 } else {
1890 // Return static default defined in CarrierConfigManager.
1891 return CarrierConfigManager.getDefaultConfig().getBoolean(key);
1892 }
1893 }
1894
1895 /**
fionaxu5803ef02016-03-08 11:48:48 -08001896 * Get the int config from carrier config manager.
1897 *
Brad Ebinger16417b42017-03-07 13:48:50 -08001898 * @param key config key defined in CarrierConfigManager
1899 * @return integer value of corresponding key.
1900 */
Brad Ebinger479f52c2017-08-28 13:19:22 -07001901 private int getIntCarrierConfig(String key) {
Brad Ebinger16417b42017-03-07 13:48:50 -08001902 int[] subIds = SubscriptionManager.getSubId(mPhoneId);
1903 int subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1904 if (subIds != null && subIds.length >= 1) {
1905 subId = subIds[0];
1906 }
1907 PersistableBundle b = null;
1908 if (mConfigManager != null) {
1909 // If an invalid subId is used, this bundle will contain default values.
1910 b = mConfigManager.getConfigForSubId(subId);
1911 }
1912 if (b != null) {
1913 return b.getInt(key);
1914 } else {
1915 // Return static default defined in CarrierConfigManager.
1916 return CarrierConfigManager.getDefaultConfig().getInt(key);
1917 }
1918 }
1919
1920 /**
Wink Savilleef36ef62014-06-11 08:39:38 -07001921 * Gets the call ID from the specified incoming call broadcast intent.
1922 *
1923 * @param incomingCallIntent the incoming call broadcast intent
1924 * @return the call ID or null if the intent does not contain it
1925 */
1926 private static String getCallId(Intent incomingCallIntent) {
1927 if (incomingCallIntent == null) {
1928 return null;
1929 }
1930
1931 return incomingCallIntent.getStringExtra(EXTRA_CALL_ID);
1932 }
1933
1934 /**
1935 * Gets the service type from the specified incoming call broadcast intent.
1936 *
1937 * @param incomingCallIntent the incoming call broadcast intent
Brad Ebinger16780ff2017-01-26 11:18:21 -08001938 * @return the session identifier or -1 if the intent does not contain it
Wink Savilleef36ef62014-06-11 08:39:38 -07001939 */
Brad Ebinger16780ff2017-01-26 11:18:21 -08001940 private static int getImsSessionId(Intent incomingCallIntent) {
Wink Savilleef36ef62014-06-11 08:39:38 -07001941 if (incomingCallIntent == null) {
1942 return (-1);
1943 }
1944
1945 return incomingCallIntent.getIntExtra(EXTRA_SERVICE_ID, -1);
1946 }
1947
1948 /**
Brad Ebingerb10b61e2017-04-18 11:45:26 -07001949 * Checks to see if the ImsService Binder is connected. If it is not, we try to create the
1950 * connection again.
Wink Savilleef36ef62014-06-11 08:39:38 -07001951 */
1952 private void checkAndThrowExceptionIfServiceUnavailable()
1953 throws ImsException {
Brad Ebinger16780ff2017-01-26 11:18:21 -08001954 if (mImsServiceProxy == null || !mImsServiceProxy.isBinderAlive()) {
1955 createImsService();
Wink Savilleef36ef62014-06-11 08:39:38 -07001956
Brad Ebinger16780ff2017-01-26 11:18:21 -08001957 if (mImsServiceProxy == null) {
Wink Savilleef36ef62014-06-11 08:39:38 -07001958 throw new ImsException("Service is unavailable",
1959 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1960 }
1961 }
1962 }
1963
Brad Ebinger16780ff2017-01-26 11:18:21 -08001964 /**
1965 * Binds the IMS service to make/receive the call. Supports two methods of exposing an
1966 * ImsService:
1967 * 1) com.android.ims.ImsService implementation in ServiceManager (deprecated).
1968 * 2) android.telephony.ims.ImsService implementation through ImsResolver.
1969 */
1970 private void createImsService() {
1971 if (!mConfigDynamicBind) {
Brad Ebinger0e170c72017-12-14 14:24:02 -08001972 // Deprecated method of binding
Brad Ebinger16780ff2017-01-26 11:18:21 -08001973 Rlog.i(TAG, "Creating ImsService using ServiceManager");
Brad Ebinger3418c132018-01-18 12:03:33 -08001974 mImsServiceProxy = ImsServiceProxyCompat.create(mContext, mPhoneId, mDeathRecipient);
Brad Ebinger16780ff2017-01-26 11:18:21 -08001975 } else {
1976 Rlog.i(TAG, "Creating ImsService using ImsResolver");
Brad Ebinger0e170c72017-12-14 14:24:02 -08001977 mImsServiceProxy = ImsServiceProxy.create(mContext, mPhoneId);
Brad Ebinger16780ff2017-01-26 11:18:21 -08001978 }
Brad Ebinger0e170c72017-12-14 14:24:02 -08001979 // Forwarding interface to tell mStatusCallbacks that the Proxy is unavailable.
1980 mImsServiceProxy.setStatusCallback(new ImsServiceProxy.IFeatureUpdate() {
1981 @Override
1982 public void notifyStateChanged() {
1983 mStatusCallbacks.forEach(ImsServiceProxy.IFeatureUpdate::notifyStateChanged);
1984 }
1985
1986 @Override
1987 public void notifyUnavailable() {
1988 mStatusCallbacks.forEach(ImsServiceProxy.IFeatureUpdate::notifyUnavailable);
1989 }
1990 });
Brad Ebinger9a0280c2017-06-01 15:58:48 -07001991 // We have created a new ImsService connection, signal for re-registration
1992 synchronized (mHasRegisteredLock) {
1993 mHasRegisteredForProxy = false;
1994 }
Etan Cohend7727462014-07-12 14:54:10 -07001995 }
1996
Wink Savilleef36ef62014-06-11 08:39:38 -07001997 /**
1998 * Creates a {@link ImsCallSession} with the specified call profile.
1999 * Use other methods, if applicable, instead of interacting with
2000 * {@link ImsCallSession} directly.
2001 *
2002 * @param serviceId a service id which is obtained from {@link ImsManager#open}
2003 * @param profile a call profile to make the call
2004 */
2005 private ImsCallSession createCallSession(int serviceId,
2006 ImsCallProfile profile) throws ImsException {
2007 try {
Brad Ebingerb10b61e2017-04-18 11:45:26 -07002008 // Throws an exception if the ImsService Feature is not ready to accept commands.
Brad Ebinger8409c972018-01-11 10:29:04 -08002009 return new ImsCallSession(mImsServiceProxy.createCallSession(serviceId, profile));
Wink Savilleef36ef62014-06-11 08:39:38 -07002010 } catch (RemoteException e) {
Brad Ebingerb10b61e2017-04-18 11:45:26 -07002011 Rlog.w(TAG, "CreateCallSession: Error, remote exception: " + e.getMessage());
2012 throw new ImsException("createCallSession()", e,
2013 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
2014
Wink Savilleef36ef62014-06-11 08:39:38 -07002015 }
2016 }
2017
Etan Cohena00c9192014-12-23 15:02:29 -08002018 private static void log(String s) {
Wink Savilleef36ef62014-06-11 08:39:38 -07002019 Rlog.d(TAG, s);
2020 }
2021
Etan Cohena00c9192014-12-23 15:02:29 -08002022 private static void loge(String s) {
Wink Savilleef36ef62014-06-11 08:39:38 -07002023 Rlog.e(TAG, s);
2024 }
2025
Etan Cohena00c9192014-12-23 15:02:29 -08002026 private static void loge(String s, Throwable t) {
Wink Savilleef36ef62014-06-11 08:39:38 -07002027 Rlog.e(TAG, s, t);
2028 }
2029
2030 /**
ram7da5a112014-07-16 20:59:27 +05302031 * Used for turning on IMS.if its off already
2032 */
Etan Cohen82f78122014-12-15 10:10:14 -08002033 private void turnOnIms() throws ImsException {
Etan Cohen0c9c09e2014-07-25 11:09:12 -07002034 checkAndThrowExceptionIfServiceUnavailable();
2035
ram7da5a112014-07-16 20:59:27 +05302036 try {
Brad Ebingerb5f30c72017-02-17 14:54:31 -08002037 mImsServiceProxy.turnOnIms();
ram7da5a112014-07-16 20:59:27 +05302038 } catch (RemoteException e) {
2039 throw new ImsException("turnOnIms() ", e, ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
2040 }
2041 }
2042
Omkar Kolangade75f3ca32014-10-24 11:10:52 -07002043 private boolean isImsTurnOffAllowed() {
Brad Ebinger479f52c2017-08-28 13:19:22 -07002044 return isTurnOffImsAllowedByPlatform()
2045 && (!isWfcEnabledByPlatform()
2046 || !isWfcEnabledByUser());
Omkar Kolangade75f3ca32014-10-24 11:10:52 -07002047 }
2048
Amit Mahajan9cba36d2016-08-11 10:17:23 -07002049 private void setLteFeatureValues(boolean turnOn) {
2050 log("setLteFeatureValues: " + turnOn);
Omkar Kolangade75f3ca32014-10-24 11:10:52 -07002051 try {
2052 ImsConfig config = getConfigInterface();
Amit Mahajan9cba36d2016-08-11 10:17:23 -07002053 if (config != null) {
Omkar Kolangade75f3ca32014-10-24 11:10:52 -07002054 config.setFeatureValue(ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_LTE,
Pavel Zhamaitsiakf4b90322016-01-26 14:34:09 -08002055 TelephonyManager.NETWORK_TYPE_LTE, turnOn ? 1 : 0, mImsConfigListener);
Pavel Zhamaitsiakff29b9d2016-04-15 12:16:57 -07002056
Brad Ebinger479f52c2017-08-28 13:19:22 -07002057 if (isVolteEnabledByPlatform()) {
2058 boolean ignoreDataEnabledChanged = getBooleanCarrierConfig(
Jack Yu57781852016-11-16 17:20:38 -08002059 CarrierConfigManager.KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS);
Brad Ebinger479f52c2017-08-28 13:19:22 -07002060 boolean enableViLte = turnOn && isVtEnabledByUser() &&
Jack Yu57781852016-11-16 17:20:38 -08002061 (ignoreDataEnabledChanged || isDataEnabled());
Pavel Zhamaitsiakff29b9d2016-04-15 12:16:57 -07002062 config.setFeatureValue(ImsConfig.FeatureConstants.FEATURE_TYPE_VIDEO_OVER_LTE,
2063 TelephonyManager.NETWORK_TYPE_LTE,
2064 enableViLte ? 1 : 0,
2065 mImsConfigListener);
2066 }
Etan Cohenb651fa52014-10-22 10:51:29 -07002067 }
Omkar Kolangade75f3ca32014-10-24 11:10:52 -07002068 } catch (ImsException e) {
Amit Mahajan9cba36d2016-08-11 10:17:23 -07002069 loge("setLteFeatureValues: exception ", e);
Etan Cohencfc784d2014-08-07 18:40:31 -07002070 }
Amit Mahajan9cba36d2016-08-11 10:17:23 -07002071 }
2072
2073 private void setAdvanced4GMode(boolean turnOn) throws ImsException {
2074 checkAndThrowExceptionIfServiceUnavailable();
2075
2076 // if turnOn: first set feature values then call turnOnIms()
2077 // if turnOff: only set feature values if IMS turn off is not allowed. If turn off is
2078 // allowed, first call turnOffIms() then set feature values
Etan Cohencfc784d2014-08-07 18:40:31 -07002079 if (turnOn) {
Amit Mahajan9cba36d2016-08-11 10:17:23 -07002080 setLteFeatureValues(turnOn);
2081 log("setAdvanced4GMode: turnOnIms");
Etan Cohencfc784d2014-08-07 18:40:31 -07002082 turnOnIms();
Amit Mahajan9cba36d2016-08-11 10:17:23 -07002083 } else {
2084 if (isImsTurnOffAllowed()) {
2085 log("setAdvanced4GMode: turnOffIms");
2086 turnOffIms();
2087 }
2088 setLteFeatureValues(turnOn);
Etan Cohencfc784d2014-08-07 18:40:31 -07002089 }
2090 }
2091
ram7da5a112014-07-16 20:59:27 +05302092 /**
2093 * Used for turning off IMS completely in order to make the device CSFB'ed.
2094 * Once turned off, all calls will be over CS.
2095 */
Etan Cohen82f78122014-12-15 10:10:14 -08002096 private void turnOffIms() throws ImsException {
Etan Cohen0c9c09e2014-07-25 11:09:12 -07002097 checkAndThrowExceptionIfServiceUnavailable();
2098
ram7da5a112014-07-16 20:59:27 +05302099 try {
Brad Ebingerb5f30c72017-02-17 14:54:31 -08002100 mImsServiceProxy.turnOffIms();
ram7da5a112014-07-16 20:59:27 +05302101 } catch (RemoteException e) {
2102 throw new ImsException("turnOffIms() ", e, ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
2103 }
2104 }
2105
Naveen Kalla525c3a22017-02-06 14:46:42 -08002106 private void addToRecentDisconnectReasons(ImsReasonInfo reason) {
2107 if (reason == null) return;
2108 while (mRecentDisconnectReasons.size() >= MAX_RECENT_DISCONNECT_REASONS) {
2109 mRecentDisconnectReasons.removeFirst();
2110 }
2111 mRecentDisconnectReasons.addLast(reason);
2112 }
2113
ram7da5a112014-07-16 20:59:27 +05302114 /**
Wink Savilleef36ef62014-06-11 08:39:38 -07002115 * Death recipient class for monitoring IMS service.
2116 */
2117 private class ImsServiceDeathRecipient implements IBinder.DeathRecipient {
2118 @Override
2119 public void binderDied() {
Brad Ebinger16780ff2017-01-26 11:18:21 -08002120 mImsServiceProxy = null;
Wink Savilleef36ef62014-06-11 08:39:38 -07002121 mUt = null;
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -05002122 mConfig = null;
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -07002123 mEcbm = null;
Tyler Gunn4d128b62016-04-13 15:44:38 -07002124 mMultiEndpoint = null;
Wink Savilleef36ef62014-06-11 08:39:38 -07002125 }
2126 }
2127
2128 /**
Brad Ebinger57b11892017-06-13 16:21:35 -07002129 * Stub implementation of the Registration listener that provides no functionality.
2130 */
2131 private class ImsRegistrationListenerBase extends IImsRegistrationListener.Stub {
2132
2133 @Override
2134 public void registrationConnected() throws RemoteException {
2135 }
2136
2137 @Override
2138 public void registrationProgressing() throws RemoteException {
2139 }
2140
2141 @Override
2142 public void registrationConnectedWithRadioTech(int imsRadioTech) throws RemoteException {
2143 }
2144
2145 @Override
2146 public void registrationProgressingWithRadioTech(int imsRadioTech) throws RemoteException {
2147 }
2148
2149 @Override
2150 public void registrationDisconnected(ImsReasonInfo imsReasonInfo) throws RemoteException {
2151 }
2152
2153 @Override
2154 public void registrationResumed() throws RemoteException {
2155 }
2156
2157 @Override
2158 public void registrationSuspended() throws RemoteException {
2159 }
2160
2161 @Override
2162 public void registrationServiceCapabilityChanged(int serviceClass, int event)
2163 throws RemoteException {
2164 }
2165
2166 @Override
2167 public void registrationFeatureCapabilityChanged(int serviceClass, int[] enabledFeatures,
2168 int[] disabledFeatures) throws RemoteException {
2169 }
2170
2171 @Override
2172 public void voiceMessageCountUpdate(int count) throws RemoteException {
2173 }
2174
2175 @Override
2176 public void registrationAssociatedUriChanged(Uri[] uris) throws RemoteException {
2177 }
2178
2179 @Override
2180 public void registrationChangeFailed(int targetAccessTech, ImsReasonInfo imsReasonInfo)
2181 throws RemoteException {
2182 }
2183 }
2184
2185 /**
Wink Savilleef36ef62014-06-11 08:39:38 -07002186 * Adapter class for {@link IImsRegistrationListener}.
2187 */
Naveen Kalla196fd3b2017-02-14 14:55:24 -08002188 private class ImsRegistrationListenerProxy extends IImsRegistrationListener.Stub {
Wink Savilleef36ef62014-06-11 08:39:38 -07002189
Omkar Kolangadea7ced642015-05-04 17:55:13 -07002190 @Deprecated
Wink Savilleef36ef62014-06-11 08:39:38 -07002191 public void registrationConnected() {
2192 if (DBG) {
2193 log("registrationConnected ::");
2194 }
2195
Brad Ebinger9a0280c2017-06-01 15:58:48 -07002196 synchronized (mRegistrationListeners) {
2197 mRegistrationListeners.forEach(l -> l.onImsConnected(
2198 ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN));
Wink Savilleef36ef62014-06-11 08:39:38 -07002199 }
2200 }
2201
Omkar Kolangadea7ced642015-05-04 17:55:13 -07002202 @Deprecated
Rekha Kumar14631742015-02-04 10:47:00 -08002203 public void registrationProgressing() {
Wink Savilleef36ef62014-06-11 08:39:38 -07002204 if (DBG) {
Rekha Kumar14631742015-02-04 10:47:00 -08002205 log("registrationProgressing ::");
Wink Savilleef36ef62014-06-11 08:39:38 -07002206 }
2207
Brad Ebinger9a0280c2017-06-01 15:58:48 -07002208 synchronized (mRegistrationListeners) {
2209 mRegistrationListeners.forEach(l -> l.onImsProgressing(
2210 ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN));
Rekha Kumar14631742015-02-04 10:47:00 -08002211 }
2212 }
2213
2214 @Override
Omkar Kolangadea7ced642015-05-04 17:55:13 -07002215 public void registrationConnectedWithRadioTech(int imsRadioTech) {
2216 // Note: imsRadioTech value maps to RIL_RADIO_TECHNOLOGY
2217 // values in ServiceState.java.
2218 if (DBG) {
2219 log("registrationConnectedWithRadioTech :: imsRadioTech=" + imsRadioTech);
2220 }
2221
Brad Ebinger9a0280c2017-06-01 15:58:48 -07002222 synchronized (mRegistrationListeners) {
2223 mRegistrationListeners.forEach(l -> l.onImsConnected(imsRadioTech));
Omkar Kolangadea7ced642015-05-04 17:55:13 -07002224 }
2225 }
2226
2227 @Override
2228 public void registrationProgressingWithRadioTech(int imsRadioTech) {
2229 // Note: imsRadioTech value maps to RIL_RADIO_TECHNOLOGY
2230 // values in ServiceState.java.
2231 if (DBG) {
2232 log("registrationProgressingWithRadioTech :: imsRadioTech=" + imsRadioTech);
2233 }
2234
Brad Ebinger9a0280c2017-06-01 15:58:48 -07002235 synchronized (mRegistrationListeners) {
2236 mRegistrationListeners.forEach(l -> l.onImsProgressing(imsRadioTech));
Omkar Kolangadea7ced642015-05-04 17:55:13 -07002237 }
2238 }
2239
2240 @Override
Rekha Kumar14631742015-02-04 10:47:00 -08002241 public void registrationDisconnected(ImsReasonInfo imsReasonInfo) {
2242 if (DBG) {
2243 log("registrationDisconnected :: imsReasonInfo" + imsReasonInfo);
2244 }
2245
Naveen Kalla525c3a22017-02-06 14:46:42 -08002246 addToRecentDisconnectReasons(imsReasonInfo);
Brad Ebinger9a0280c2017-06-01 15:58:48 -07002247 synchronized (mRegistrationListeners) {
2248 mRegistrationListeners.forEach(l -> l.onImsDisconnected(imsReasonInfo));
Wink Savilleef36ef62014-06-11 08:39:38 -07002249 }
2250 }
2251
2252 @Override
2253 public void registrationResumed() {
2254 if (DBG) {
2255 log("registrationResumed ::");
2256 }
2257
Brad Ebinger9a0280c2017-06-01 15:58:48 -07002258 synchronized (mRegistrationListeners) {
2259 mRegistrationListeners.forEach(ImsConnectionStateListener::onImsResumed);
Wink Savilleef36ef62014-06-11 08:39:38 -07002260 }
2261 }
2262
2263 @Override
2264 public void registrationSuspended() {
2265 if (DBG) {
2266 log("registrationSuspended ::");
2267 }
2268
Brad Ebinger9a0280c2017-06-01 15:58:48 -07002269 synchronized (mRegistrationListeners) {
2270 mRegistrationListeners.forEach(ImsConnectionStateListener::onImsSuspended);
Wink Savilleef36ef62014-06-11 08:39:38 -07002271 }
2272 }
2273
2274 @Override
2275 public void registrationServiceCapabilityChanged(int serviceClass, int event) {
2276 log("registrationServiceCapabilityChanged :: serviceClass=" +
2277 serviceClass + ", event=" + event);
2278
Brad Ebinger9a0280c2017-06-01 15:58:48 -07002279 synchronized (mRegistrationListeners) {
2280 mRegistrationListeners.forEach(l -> l.onImsConnected(
2281 ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN));
Wink Savilleef36ef62014-06-11 08:39:38 -07002282 }
2283 }
ram7da5a112014-07-16 20:59:27 +05302284
2285 @Override
2286 public void registrationFeatureCapabilityChanged(int serviceClass,
2287 int[] enabledFeatures, int[] disabledFeatures) {
2288 log("registrationFeatureCapabilityChanged :: serviceClass=" +
2289 serviceClass);
Brad Ebinger9a0280c2017-06-01 15:58:48 -07002290
2291 synchronized (mRegistrationListeners) {
2292 mRegistrationListeners.forEach(l -> l.onFeatureCapabilityChanged(serviceClass,
2293 enabledFeatures, disabledFeatures));
Libin.Tang@motorola.come2296782014-08-19 14:20:01 -05002294 }
ram7da5a112014-07-16 20:59:27 +05302295 }
2296
Shriram Ganeshd3adfad2015-05-31 10:06:15 -07002297 @Override
2298 public void voiceMessageCountUpdate(int count) {
2299 log("voiceMessageCountUpdate :: count=" + count);
2300
Brad Ebinger9a0280c2017-06-01 15:58:48 -07002301 synchronized (mRegistrationListeners) {
2302 mRegistrationListeners.forEach(l -> l.onVoiceMessageCountChanged(count));
Shriram Ganeshd3adfad2015-05-31 10:06:15 -07002303 }
2304 }
2305
Pavel Zhamaitsiak4de9cbb2016-02-11 17:21:05 -08002306 @Override
2307 public void registrationAssociatedUriChanged(Uri[] uris) {
2308 if (DBG) log("registrationAssociatedUriChanged ::");
2309
Brad Ebinger9a0280c2017-06-01 15:58:48 -07002310 synchronized (mRegistrationListeners) {
2311 mRegistrationListeners.forEach(l -> l.registrationAssociatedUriChanged(uris));
Pavel Zhamaitsiak4de9cbb2016-02-11 17:21:05 -08002312 }
2313 }
Meng Wangbb98b9b2016-12-07 16:27:15 -08002314
2315 @Override
2316 public void registrationChangeFailed(int targetAccessTech, ImsReasonInfo imsReasonInfo) {
2317 if (DBG) log("registrationChangeFailed :: targetAccessTech=" + targetAccessTech +
2318 ", imsReasonInfo=" + imsReasonInfo);
2319
Brad Ebinger9a0280c2017-06-01 15:58:48 -07002320 synchronized (mRegistrationListeners) {
2321 mRegistrationListeners.forEach(l -> l.onRegistrationChangeFailed(targetAccessTech,
2322 imsReasonInfo));
Meng Wangbb98b9b2016-12-07 16:27:15 -08002323 }
2324 }
Wink Savilleef36ef62014-06-11 08:39:38 -07002325 }
Tyler Gunn4d128b62016-04-13 15:44:38 -07002326
Brad Ebinger0e170c72017-12-14 14:24:02 -08002327 // New API for Registration, uses ImsConnectionStateListener for backwards compatibility with
2328 // deprecated APIs.
2329 private class ImsRegistrationCallback extends IImsRegistrationCallback.Stub {
2330
2331 @Override
2332 public void onRegistered(int imsRadioTech) {
2333 if (DBG) log("onRegistered ::");
2334
2335 synchronized (mRegistrationListeners) {
2336 mRegistrationListeners.forEach(l -> l.onRegistered(imsRadioTech));
2337 }
2338 }
2339
2340 @Override
2341 public void onRegistering(int imsRadioTech) {
2342 if (DBG) log("onRegistering ::");
2343
2344 synchronized (mRegistrationListeners) {
2345 mRegistrationListeners.forEach(l -> l.onRegistering(imsRadioTech));
2346 }
2347 }
2348
2349 @Override
2350 public void onDeregistered(ImsReasonInfo imsReasonInfo) {
2351 if (DBG) log("onDeregistered ::");
2352
2353 synchronized (mRegistrationListeners) {
2354 mRegistrationListeners.forEach(l -> l.onDeregistered(imsReasonInfo));
2355 }
2356 }
2357
2358 @Override
2359 public void onTechnologyChangeFailed(int targetRadioTech, ImsReasonInfo imsReasonInfo) {
2360 if (DBG) log("onTechnologyChangeFailed :: targetAccessTech=" + targetRadioTech +
2361 ", imsReasonInfo=" + imsReasonInfo);
2362
2363 synchronized (mRegistrationListeners) {
2364 mRegistrationListeners.forEach(l -> l.onTechnologyChangeFailed(targetRadioTech,
2365 imsReasonInfo));
2366 }
2367 }
2368
2369 @Override
2370 public void onSubscriberAssociatedUriChanged(Uri[] uris) {
2371 if (DBG) log("onSubscriberAssociatedUriChanged");
2372 synchronized (mRegistrationListeners) {
2373 mRegistrationListeners.forEach(l -> l.onSubscriberAssociatedUriChanged(uris));
2374 }
2375 }
2376 }
2377
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -07002378 /**
2379 * Gets the ECBM interface to request ECBM exit.
2380 *
2381 * @param serviceId a service id which is obtained from {@link ImsManager#open}
2382 * @return the ECBM interface instance
2383 * @throws ImsException if getting the ECBM interface results in an error
2384 */
2385 public ImsEcbm getEcbmInterface(int serviceId) throws ImsException {
Brad Ebinger138b4a62017-06-20 16:29:50 -07002386 if (mEcbm != null && mEcbm.isBinderAlive()) {
2387 return mEcbm;
2388 }
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -07002389
Brad Ebinger138b4a62017-06-20 16:29:50 -07002390 checkAndThrowExceptionIfServiceUnavailable();
2391 try {
2392 IImsEcbm iEcbm = mImsServiceProxy.getEcbmInterface();
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -07002393
Brad Ebinger138b4a62017-06-20 16:29:50 -07002394 if (iEcbm == null) {
2395 throw new ImsException("getEcbmInterface()",
2396 ImsReasonInfo.CODE_ECBM_NOT_SUPPORTED);
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -07002397 }
Brad Ebinger138b4a62017-06-20 16:29:50 -07002398 mEcbm = new ImsEcbm(iEcbm);
2399 } catch (RemoteException e) {
2400 throw new ImsException("getEcbmInterface()", e,
2401 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -07002402 }
2403 return mEcbm;
2404 }
Pavel Zhamaitsiak8c065f52015-11-10 14:36:44 -08002405
Mohamed Abdalkaderf8800da2018-01-10 13:29:26 -08002406 public void sendSms(int token, int messageRef, String format, String smsc, boolean isRetry,
2407 byte[] pdu) throws ImsException {
2408 try {
2409 mImsServiceProxy.sendSms(token, messageRef, format, smsc, isRetry, pdu);
2410 } catch (RemoteException e) {
2411 throw new ImsException("sendSms()", e, ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
2412 }
2413 }
2414
2415 public void acknowledgeSms(int token, int messageRef, int result) throws ImsException {
2416 try {
2417 mImsServiceProxy.acknowledgeSms(token, messageRef, result);
2418 } catch (RemoteException e) {
2419 throw new ImsException("acknowledgeSms()", e,
2420 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
2421 }
2422 }
2423
2424 public void acknowledgeSmsReport(int token, int messageRef, int result) throws ImsException{
2425 try {
2426 mImsServiceProxy.acknowledgeSmsReport(token, messageRef, result);
2427 } catch (RemoteException e) {
2428 throw new ImsException("acknowledgeSmsReport()", e,
2429 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
2430 }
2431 }
2432
2433 public String getSmsFormat() throws ImsException{
2434 try {
2435 return mImsServiceProxy.getSmsFormat();
2436 } catch (RemoteException e) {
2437 throw new ImsException("getSmsFormat()", e,
2438 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
2439 }
2440 }
2441
2442 public void setSmsListener(IImsSmsListener listener) throws ImsException {
2443 try {
2444 mImsServiceProxy.setSmsListener(listener);
2445 } catch (RemoteException e) {
2446 throw new ImsException("setSmsListener()", e,
2447 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
2448 }
2449 }
Mohamed Abdalkader415e6de2018-01-19 19:48:31 -08002450
Mohamed Abdalkader4d59b1b2018-01-23 13:11:00 -08002451 public void onSmsReady() throws ImsException{
2452 try {
2453 mImsServiceProxy.onSmsReady();
2454 } catch (RemoteException e) {
2455 throw new ImsException("onSmsReady()", e,
2456 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
2457 }
2458 }
2459
Mohamed Abdalkader415e6de2018-01-19 19:48:31 -08002460 public void addRegistrationCallback(ImsRegistrationImplBase.Callback callback) {
2461 // TODO: implement (coming in ag/3472519)
2462 }
2463
2464 public void addCapabilitiesCallback(ImsFeature.CapabilityCallback callback) {
2465 // TODO: implement (coming in ag/3472519)
2466 }
2467
Pavel Zhamaitsiak8c065f52015-11-10 14:36:44 -08002468 /**
Tyler Gunn4d128b62016-04-13 15:44:38 -07002469 * Gets the Multi-Endpoint interface to subscribe to multi-enpoint notifications..
2470 *
2471 * @param serviceId a service id which is obtained from {@link ImsManager#open}
2472 * @return the multi-endpoint interface instance
2473 * @throws ImsException if getting the multi-endpoint interface results in an error
2474 */
2475 public ImsMultiEndpoint getMultiEndpointInterface(int serviceId) throws ImsException {
Brad Ebinger138b4a62017-06-20 16:29:50 -07002476 if (mMultiEndpoint != null && mMultiEndpoint.isBinderAlive()) {
2477 return mMultiEndpoint;
Tyler Gunn4d128b62016-04-13 15:44:38 -07002478 }
Brad Ebinger138b4a62017-06-20 16:29:50 -07002479
2480 checkAndThrowExceptionIfServiceUnavailable();
2481 try {
2482 IImsMultiEndpoint iImsMultiEndpoint = mImsServiceProxy.getMultiEndpointInterface();
2483
2484 if (iImsMultiEndpoint == null) {
2485 throw new ImsException("getMultiEndpointInterface()",
2486 ImsReasonInfo.CODE_MULTIENDPOINT_NOT_SUPPORTED);
2487 }
2488 mMultiEndpoint = new ImsMultiEndpoint(iImsMultiEndpoint);
2489 } catch (RemoteException e) {
2490 throw new ImsException("getMultiEndpointInterface()", e,
2491 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
2492 }
2493
Tyler Gunn4d128b62016-04-13 15:44:38 -07002494 return mMultiEndpoint;
2495 }
2496
2497 /**
Pavel Zhamaitsiak8c065f52015-11-10 14:36:44 -08002498 * Resets ImsManager settings back to factory defaults.
2499 *
Brad Ebinger479f52c2017-08-28 13:19:22 -07002500 * @deprecated Doesn't support MSIM devices. Use {@link #factoryReset()} instead.
Brad Ebinger16417b42017-03-07 13:48:50 -08002501 *
Pavel Zhamaitsiak8c065f52015-11-10 14:36:44 -08002502 * @hide
2503 */
2504 public static void factoryReset(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -07002505 ImsManager mgr = ImsManager.getInstance(context,
2506 SubscriptionManager.getDefaultVoicePhoneId());
2507 if (mgr != null) {
2508 mgr.factoryReset();
2509 }
2510 loge("factoryReset: ImsManager null.");
Pavel Zhamaitsiak8c065f52015-11-10 14:36:44 -08002511 }
Jack Yu2f102bd2015-12-28 15:31:48 -08002512
Brad Ebinger16417b42017-03-07 13:48:50 -08002513 /**
2514 * Resets ImsManager settings back to factory defaults.
2515 *
2516 * @hide
2517 */
Brad Ebinger479f52c2017-08-28 13:19:22 -07002518 public void factoryReset() {
Malcolm Chen201d2312017-09-28 17:28:45 -07002519 // Set VoLTE to default
2520 SubscriptionManager.setSubscriptionProperty(getSubId(),
2521 SubscriptionManager.ENHANCED_4G_MODE_ENABLED, booleanToPropertyString(true));
Brad Ebinger16417b42017-03-07 13:48:50 -08002522
2523 // Set VoWiFi to default
Malcolm Chen201d2312017-09-28 17:28:45 -07002524 SubscriptionManager.setSubscriptionProperty(getSubId(),
2525 SubscriptionManager.WFC_IMS_ENABLED,
2526 booleanToPropertyString(getBooleanCarrierConfig(
2527 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ENABLED_BOOL)));
Brad Ebinger16417b42017-03-07 13:48:50 -08002528
2529 // Set VoWiFi mode to default
Malcolm Chen201d2312017-09-28 17:28:45 -07002530 SubscriptionManager.setSubscriptionProperty(getSubId(),
2531 SubscriptionManager.WFC_IMS_MODE,
2532 Integer.toString(getIntCarrierConfig(
2533 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_MODE_INT)));
Brad Ebinger16417b42017-03-07 13:48:50 -08002534
2535 // Set VoWiFi roaming to default
Malcolm Chen201d2312017-09-28 17:28:45 -07002536 SubscriptionManager.setSubscriptionProperty(getSubId(),
2537 SubscriptionManager.WFC_IMS_ROAMING_ENABLED,
2538 booleanToPropertyString(getBooleanCarrierConfig(
2539 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_ENABLED_BOOL)));
Brad Ebinger16417b42017-03-07 13:48:50 -08002540
2541 // Set VT to default
Malcolm Chen201d2312017-09-28 17:28:45 -07002542 SubscriptionManager.setSubscriptionProperty(getSubId(),
2543 SubscriptionManager.VT_IMS_ENABLED, booleanToPropertyString(true));
Brad Ebinger16417b42017-03-07 13:48:50 -08002544
2545 // Push settings to ImsConfig
Brad Ebinger479f52c2017-08-28 13:19:22 -07002546 updateImsServiceConfig(true);
Brad Ebinger16417b42017-03-07 13:48:50 -08002547 }
2548
Amit Mahajan24f7b162016-07-21 16:33:53 -07002549 private boolean isDataEnabled() {
2550 return SystemProperties.getBoolean(DATA_ENABLED_PROP, true);
2551 }
2552
Jack Yu643ffe42016-07-08 14:25:46 -07002553 /**
2554 * Set data enabled/disabled flag.
2555 * @param enabled True if data is enabled, otherwise disabled.
2556 */
2557 public void setDataEnabled(boolean enabled) {
2558 log("setDataEnabled: " + enabled);
Amit Mahajan24f7b162016-07-21 16:33:53 -07002559 SystemProperties.set(DATA_ENABLED_PROP, enabled ? TRUE : FALSE);
2560 }
2561
2562 private boolean isVolteProvisioned() {
2563 return SystemProperties.getBoolean(VOLTE_PROVISIONED_PROP, true);
2564 }
2565
2566 private void setVolteProvisionedProperty(boolean provisioned) {
2567 SystemProperties.set(VOLTE_PROVISIONED_PROP, provisioned ? TRUE : FALSE);
2568 }
2569
2570 private boolean isWfcProvisioned() {
2571 return SystemProperties.getBoolean(WFC_PROVISIONED_PROP, true);
2572 }
2573
2574 private void setWfcProvisionedProperty(boolean provisioned) {
2575 SystemProperties.set(WFC_PROVISIONED_PROP, provisioned ? TRUE : FALSE);
2576 }
2577
2578 private boolean isVtProvisioned() {
2579 return SystemProperties.getBoolean(VT_PROVISIONED_PROP, true);
2580 }
2581
2582 private void setVtProvisionedProperty(boolean provisioned) {
2583 SystemProperties.set(VT_PROVISIONED_PROP, provisioned ? TRUE : FALSE);
Jack Yu643ffe42016-07-08 14:25:46 -07002584 }
2585
Malcolm Chen201d2312017-09-28 17:28:45 -07002586 private static String booleanToPropertyString(boolean bool) {
2587 return bool ? "1" : "0";
2588 }
2589
2590
Jack Yu2f102bd2015-12-28 15:31:48 -08002591 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
2592 pw.println("ImsManager:");
2593 pw.println(" mPhoneId = " + mPhoneId);
2594 pw.println(" mConfigUpdated = " + mConfigUpdated);
Brad Ebinger16780ff2017-01-26 11:18:21 -08002595 pw.println(" mImsServiceProxy = " + mImsServiceProxy);
Amit Mahajan24f7b162016-07-21 16:33:53 -07002596 pw.println(" mDataEnabled = " + isDataEnabled());
Brad Ebinger479f52c2017-08-28 13:19:22 -07002597 pw.println(" ignoreDataEnabledChanged = " + getBooleanCarrierConfig(
Jack Yu57781852016-11-16 17:20:38 -08002598 CarrierConfigManager.KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS));
Jack Yu2f102bd2015-12-28 15:31:48 -08002599
Brad Ebinger479f52c2017-08-28 13:19:22 -07002600 pw.println(" isGbaValid = " + isGbaValid());
Jack Yu2f102bd2015-12-28 15:31:48 -08002601 pw.println(" isImsTurnOffAllowed = " + isImsTurnOffAllowed());
Brad Ebinger479f52c2017-08-28 13:19:22 -07002602 pw.println(" isNonTtyOrTtyOnVolteEnabled = " + isNonTtyOrTtyOnVolteEnabled());
Jack Yu2f102bd2015-12-28 15:31:48 -08002603
Brad Ebinger479f52c2017-08-28 13:19:22 -07002604 pw.println(" isVolteEnabledByPlatform = " + isVolteEnabledByPlatform());
2605 pw.println(" isVolteProvisionedOnDevice = " + isVolteProvisionedOnDevice());
Jack Yu2f102bd2015-12-28 15:31:48 -08002606 pw.println(" isEnhanced4gLteModeSettingEnabledByUser = " +
Brad Ebinger479f52c2017-08-28 13:19:22 -07002607 isEnhanced4gLteModeSettingEnabledByUser());
2608 pw.println(" isVtEnabledByPlatform = " + isVtEnabledByPlatform());
2609 pw.println(" isVtEnabledByUser = " + isVtEnabledByUser());
Jack Yu2f102bd2015-12-28 15:31:48 -08002610
Brad Ebinger479f52c2017-08-28 13:19:22 -07002611 pw.println(" isWfcEnabledByPlatform = " + isWfcEnabledByPlatform());
2612 pw.println(" isWfcEnabledByUser = " + isWfcEnabledByUser());
2613 pw.println(" getWfcMode = " + getWfcMode());
2614 pw.println(" isWfcRoamingEnabledByUser = " + isWfcRoamingEnabledByUser());
Jack Yu2f102bd2015-12-28 15:31:48 -08002615
Brad Ebinger479f52c2017-08-28 13:19:22 -07002616 pw.println(" isVtProvisionedOnDevice = " + isVtProvisionedOnDevice());
2617 pw.println(" isWfcProvisionedOnDevice = " + isWfcProvisionedOnDevice());
Jack Yu2f102bd2015-12-28 15:31:48 -08002618 pw.flush();
2619 }
Wink Savilleef36ef62014-06-11 08:39:38 -07002620}