blob: 305735dc8acdfe16d7b84531a91fbdc69174c565 [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;
31import android.os.ServiceManager;
Etan Cohenaf55a402014-09-04 22:34:41 -070032import android.os.SystemProperties;
Etan Cohen82f78122014-12-15 10:10:14 -080033import android.provider.Settings;
34import android.telecom.TelecomManager;
Junda Liue7663c02015-06-23 11:16:26 -070035import android.telephony.CarrierConfigManager;
Wink Savilleef36ef62014-06-11 08:39:38 -070036import android.telephony.Rlog;
Meng Wangbb98b9b2016-12-07 16:27:15 -080037import android.telephony.ServiceState;
Etan Cohen82f78122014-12-15 10:10:14 -080038import android.telephony.SubscriptionManager;
Etan Cohencfc784d2014-08-07 18:40:31 -070039import android.telephony.TelephonyManager;
Brad Ebinger16780ff2017-01-26 11:18:21 -080040import android.telephony.ims.ImsServiceProxy;
41import android.telephony.ims.ImsServiceProxyCompat;
42import android.telephony.ims.feature.ImsFeature;
Hall Liue511a202017-08-17 15:49:58 -070043import android.util.Log;
Wink Savilleef36ef62014-06-11 08:39:38 -070044
45import com.android.ims.internal.IImsCallSession;
Naveen Kalla525c3a22017-02-06 14:46:42 -080046import com.android.ims.internal.IImsConfig;
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -070047import com.android.ims.internal.IImsEcbm;
Tyler Gunn4d128b62016-04-13 15:44:38 -070048import com.android.ims.internal.IImsMultiEndpoint;
Wink Savilleef36ef62014-06-11 08:39:38 -070049import com.android.ims.internal.IImsRegistrationListener;
Brad Ebinger16780ff2017-01-26 11:18:21 -080050import com.android.ims.internal.IImsServiceController;
Wink Savilleef36ef62014-06-11 08:39:38 -070051import com.android.ims.internal.IImsUt;
52import com.android.ims.internal.ImsCallSession;
Brad Ebinger16780ff2017-01-26 11:18:21 -080053import com.android.internal.annotations.VisibleForTesting;
Brad Ebingerbe6cb672017-08-25 14:55:00 -070054import com.android.internal.telephony.ExponentialBackoff;
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -050055
Jack Yu2f102bd2015-12-28 15:31:48 -080056import java.io.FileDescriptor;
57import java.io.PrintWriter;
Naveen Kalla525c3a22017-02-06 14:46:42 -080058import java.util.ArrayList;
Etan Cohend7727462014-07-12 14:54:10 -070059import java.util.HashMap;
Naveen Kalla525c3a22017-02-06 14:46:42 -080060import java.util.concurrent.ConcurrentLinkedDeque;
Brad Ebinger16780ff2017-01-26 11:18:21 -080061import java.util.HashSet;
Brad Ebinger16780ff2017-01-26 11:18:21 -080062import java.util.Set;
Etan Cohend7727462014-07-12 14:54:10 -070063
Wink Savilleef36ef62014-06-11 08:39:38 -070064/**
65 * Provides APIs for IMS services, such as initiating IMS calls, and provides access to
66 * the operator's IMS network. This class is the starting point for any IMS actions.
67 * You can acquire an instance of it with {@link #getInstance getInstance()}.</p>
68 * <p>The APIs in this class allows you to:</p>
69 *
70 * @hide
71 */
72public class ImsManager {
Etan Cohen19604c02014-08-11 14:32:57 -070073
Etan Cohenaf55a402014-09-04 22:34:41 -070074 /*
75 * Debug flag to override configuration flag
76 */
Etan Cohenb651fa52014-10-22 10:51:29 -070077 public static final String PROPERTY_DBG_VOLTE_AVAIL_OVERRIDE = "persist.dbg.volte_avail_ovr";
78 public static final int PROPERTY_DBG_VOLTE_AVAIL_OVERRIDE_DEFAULT = 0;
Etan Cohenea2b5832014-10-23 18:50:35 -070079 public static final String PROPERTY_DBG_VT_AVAIL_OVERRIDE = "persist.dbg.vt_avail_ovr";
80 public static final int PROPERTY_DBG_VT_AVAIL_OVERRIDE_DEFAULT = 0;
Etan Cohena00c9192014-12-23 15:02:29 -080081 public static final String PROPERTY_DBG_WFC_AVAIL_OVERRIDE = "persist.dbg.wfc_avail_ovr";
82 public static final int PROPERTY_DBG_WFC_AVAIL_OVERRIDE_DEFAULT = 0;
Meng Wang9352c432016-06-08 14:22:20 -070083 public static final String PROPERTY_DBG_ALLOW_IMS_OFF_OVERRIDE = "persist.dbg.allow_ims_off";
84 public static final int PROPERTY_DBG_ALLOW_IMS_OFF_OVERRIDE_DEFAULT = 0;
Etan Cohenaf55a402014-09-04 22:34:41 -070085
Wink Savilleef36ef62014-06-11 08:39:38 -070086 /**
87 * For accessing the IMS related service.
88 * Internal use only.
89 * @hide
90 */
Etan Cohend7727462014-07-12 14:54:10 -070091 private static final String IMS_SERVICE = "ims";
Wink Savilleef36ef62014-06-11 08:39:38 -070092
93 /**
94 * The result code to be sent back with the incoming call {@link PendingIntent}.
95 * @see #open(PendingIntent, ImsConnectionStateListener)
96 */
97 public static final int INCOMING_CALL_RESULT_CODE = 101;
98
99 /**
100 * Key to retrieve the call ID from an incoming call intent.
101 * @see #open(PendingIntent, ImsConnectionStateListener)
102 */
103 public static final String EXTRA_CALL_ID = "android:imsCallID";
104
105 /**
106 * Action to broadcast when ImsService is up.
107 * Internal use only.
Brad Ebinger16780ff2017-01-26 11:18:21 -0800108 * @deprecated
Wink Savilleef36ef62014-06-11 08:39:38 -0700109 * @hide
110 */
111 public static final String ACTION_IMS_SERVICE_UP =
112 "com.android.ims.IMS_SERVICE_UP";
113
114 /**
115 * Action to broadcast when ImsService is down.
116 * Internal use only.
Brad Ebinger16780ff2017-01-26 11:18:21 -0800117 * @deprecated
Wink Savilleef36ef62014-06-11 08:39:38 -0700118 * @hide
119 */
120 public static final String ACTION_IMS_SERVICE_DOWN =
121 "com.android.ims.IMS_SERVICE_DOWN";
122
123 /**
Pavel Zhamaitsiak0c2f15c2015-03-12 15:37:54 -0700124 * Action to broadcast when ImsService registration fails.
125 * Internal use only.
126 * @hide
127 */
128 public static final String ACTION_IMS_REGISTRATION_ERROR =
129 "com.android.ims.REGISTRATION_ERROR";
130
131 /**
Etan Cohend7727462014-07-12 14:54:10 -0700132 * Part of the ACTION_IMS_SERVICE_UP or _DOWN intents.
Etan Cohenabbd7882014-09-26 22:35:35 -0700133 * A long value; the phone ID corresponding to the IMS service coming up or down.
Etan Cohend7727462014-07-12 14:54:10 -0700134 * Internal use only.
135 * @hide
136 */
Etan Cohenabbd7882014-09-26 22:35:35 -0700137 public static final String EXTRA_PHONE_ID = "android:phone_id";
Etan Cohend7727462014-07-12 14:54:10 -0700138
139 /**
Wink Savilleef36ef62014-06-11 08:39:38 -0700140 * Action for the incoming call intent for the Phone app.
141 * Internal use only.
142 * @hide
143 */
144 public static final String ACTION_IMS_INCOMING_CALL =
145 "com.android.ims.IMS_INCOMING_CALL";
146
147 /**
148 * Part of the ACTION_IMS_INCOMING_CALL intents.
149 * An integer value; service identifier obtained from {@link ImsManager#open}.
150 * Internal use only.
151 * @hide
152 */
153 public static final String EXTRA_SERVICE_ID = "android:imsServiceId";
154
155 /**
156 * Part of the ACTION_IMS_INCOMING_CALL intents.
157 * An boolean value; Flag to indicate that the incoming call is a normal call or call for USSD.
158 * The value "true" indicates that the incoming call is for USSD.
159 * Internal use only.
160 * @hide
161 */
162 public static final String EXTRA_USSD = "android:ussd";
163
Shriram Ganeshd3adfad2015-05-31 10:06:15 -0700164 /**
165 * Part of the ACTION_IMS_INCOMING_CALL intents.
166 * A boolean value; Flag to indicate whether the call is an unknown
167 * dialing call. Such calls are originated by sending commands (like
168 * AT commands) directly to modem without Android involvement.
169 * Even though they are not incoming calls, they are propagated
170 * to Phone app using same ACTION_IMS_INCOMING_CALL intent.
171 * Internal use only.
172 * @hide
173 */
Anju Mathapati9c033792015-06-16 16:33:16 -0700174 public static final String EXTRA_IS_UNKNOWN_CALL = "android:isUnknown";
Shriram Ganeshd3adfad2015-05-31 10:06:15 -0700175
Wink Savilleef36ef62014-06-11 08:39:38 -0700176 private static final String TAG = "ImsManager";
177 private static final boolean DBG = true;
178
Wink Saville1e5a38a2014-10-23 10:24:46 -0700179 private static HashMap<Integer, ImsManager> sImsManagerInstances =
180 new HashMap<Integer, ImsManager>();
Etan Cohend7727462014-07-12 14:54:10 -0700181
Wink Savilleef36ef62014-06-11 08:39:38 -0700182 private Context mContext;
Brad Ebinger16417b42017-03-07 13:48:50 -0800183 private CarrierConfigManager mConfigManager;
Etan Cohenabbd7882014-09-26 22:35:35 -0700184 private int mPhoneId;
Brad Ebinger16780ff2017-01-26 11:18:21 -0800185 private final boolean mConfigDynamicBind;
186 private ImsServiceProxyCompat mImsServiceProxy = null;
Wink Savilleef36ef62014-06-11 08:39:38 -0700187 private ImsServiceDeathRecipient mDeathRecipient = new ImsServiceDeathRecipient();
188 // Ut interface for the supplementary service configuration
189 private ImsUt mUt = null;
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -0500190 // Interface to get/set ims config items
191 private ImsConfig mConfig = null;
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -0700192 private boolean mConfigUpdated = false;
Wink Savilleef36ef62014-06-11 08:39:38 -0700193
Pavel Zhamaitsiakf4b90322016-01-26 14:34:09 -0800194 private ImsConfigListener mImsConfigListener;
195
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -0700196 // ECBM interface
197 private ImsEcbm mEcbm = null;
198
Tyler Gunn4d128b62016-04-13 15:44:38 -0700199 private ImsMultiEndpoint mMultiEndpoint = null;
200
Brad Ebinger16780ff2017-01-26 11:18:21 -0800201 private Set<ImsServiceProxy.INotifyStatusChanged> mStatusCallbacks = new HashSet<>();
202
203 // Keep track of the ImsRegistrationListenerProxys that have been created so that we can
204 // remove them from the ImsService.
Brad Ebinger64470942017-06-01 15:58:48 -0700205 private final Set<ImsConnectionStateListener> mRegistrationListeners = new HashSet<>();
206
207 private final ImsRegistrationListenerProxy mRegistrationListenerProxy =
208 new ImsRegistrationListenerProxy();
209
210 // When true, we have registered the mRegistrationListenerProxy with the ImsService. Don't do
211 // it again.
212 private boolean mHasRegisteredForProxy = false;
213 private final Object mHasRegisteredLock = new Object();
Brad Ebinger16780ff2017-01-26 11:18:21 -0800214
Amit Mahajan24f7b162016-07-21 16:33:53 -0700215 // SystemProperties used as cache
216 private static final String VOLTE_PROVISIONED_PROP = "net.lte.ims.volte.provisioned";
217 private static final String WFC_PROVISIONED_PROP = "net.lte.ims.wfc.provisioned";
218 private static final String VT_PROVISIONED_PROP = "net.lte.ims.vt.provisioned";
Jack Yu643ffe42016-07-08 14:25:46 -0700219 // Flag indicating data enabled or not. This flag should be in sync with
220 // DcTracker.isDataEnabled(). The flag will be set later during boot up.
Amit Mahajan24f7b162016-07-21 16:33:53 -0700221 private static final String DATA_ENABLED_PROP = "net.lte.ims.data.enabled";
222
223 public static final String TRUE = "true";
224 public static final String FALSE = "false";
Jack Yu643ffe42016-07-08 14:25:46 -0700225
Naveen Kalla525c3a22017-02-06 14:46:42 -0800226 // mRecentDisconnectReasons stores the last 16 disconnect reasons
227 private static final int MAX_RECENT_DISCONNECT_REASONS = 16;
228 private ConcurrentLinkedDeque<ImsReasonInfo> mRecentDisconnectReasons =
229 new ConcurrentLinkedDeque<>();
230
Brad Ebingerbe6cb672017-08-25 14:55:00 -0700231 // Exponential backoff for provisioning cache update. May be null for instances of ImsManager
232 // that are not on a thread supporting a looper.
233 private ExponentialBackoff mProvisionBackoff;
234 // Initial Provisioning check delay in ms
235 private static final long BACKOFF_INITIAL_DELAY_MS = 500;
236 // Max Provisioning check delay in ms (5 Minutes)
237 private static final long BACKOFF_MAX_DELAY_MS = 300000;
238 // Multiplier for exponential delay
239 private static final int BACKOFF_MULTIPLIER = 2;
Malcolm Chen212ca652017-09-28 17:28:45 -0700240 // -1 indicates a subscriptionProperty value that is never set.
241 private static final int SUB_PROPERTY_NOT_INITIALIZED = -1;
Brad Ebingerbe6cb672017-08-25 14:55:00 -0700242
243
Wink Savilleef36ef62014-06-11 08:39:38 -0700244 /**
245 * Gets a manager instance.
246 *
247 * @param context application context for creating the manager object
Etan Cohenabbd7882014-09-26 22:35:35 -0700248 * @param phoneId the phone ID for the IMS Service
249 * @return the manager instance corresponding to the phoneId
Wink Savilleef36ef62014-06-11 08:39:38 -0700250 */
Etan Cohenabbd7882014-09-26 22:35:35 -0700251 public static ImsManager getInstance(Context context, int phoneId) {
Etan Cohend7727462014-07-12 14:54:10 -0700252 synchronized (sImsManagerInstances) {
Naveen Kalla525c3a22017-02-06 14:46:42 -0800253 if (sImsManagerInstances.containsKey(phoneId)) {
Brad Ebinger096d95c2017-06-19 15:43:08 -0700254 ImsManager m = sImsManagerInstances.get(phoneId);
255 // May be null for some tests
256 if (m != null) {
257 m.connectIfServiceIsAvailable();
258 }
259 return m;
Naveen Kalla525c3a22017-02-06 14:46:42 -0800260 }
Wink Savilleef36ef62014-06-11 08:39:38 -0700261
Etan Cohenabbd7882014-09-26 22:35:35 -0700262 ImsManager mgr = new ImsManager(context, phoneId);
263 sImsManagerInstances.put(phoneId, mgr);
Etan Cohend7727462014-07-12 14:54:10 -0700264
265 return mgr;
266 }
Wink Savilleef36ef62014-06-11 08:39:38 -0700267 }
268
Etan Cohen45b5f312014-08-19 15:55:08 -0700269 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800270 * Returns the user configuration of Enhanced 4G LTE Mode setting.
271 *
272 * @deprecated Doesn't support MSIM devices. Use
Brad Ebingeref267192017-08-28 13:19:22 -0700273 * {@link #isEnhanced4gLteModeSettingEnabledByUser()} instead.
Etan Cohen45b5f312014-08-19 15:55:08 -0700274 */
275 public static boolean isEnhanced4gLteModeSettingEnabledByUser(Context context) {
Brad Ebingeref267192017-08-28 13:19:22 -0700276 ImsManager mgr = ImsManager.getInstance(context,
277 SubscriptionManager.getDefaultVoicePhoneId());
278 if (mgr != null) {
279 return mgr.isEnhanced4gLteModeSettingEnabledByUser();
Sungmin Choi2f1af952016-02-01 17:15:35 +0900280 }
Brad Ebingeref267192017-08-28 13:19:22 -0700281 loge("isEnhanced4gLteModeSettingEnabledByUser: ImsManager null, returning default value.");
282 return false;
Etan Cohen45b5f312014-08-19 15:55:08 -0700283 }
284
285 /**
Malcolm Chen212ca652017-09-28 17:28:45 -0700286 * Returns the user configuration of Enhanced 4G LTE Mode setting for slot. If not set, it
287 * returns true as default value.
Brad Ebinger16417b42017-03-07 13:48:50 -0800288 */
Brad Ebingeref267192017-08-28 13:19:22 -0700289 public boolean isEnhanced4gLteModeSettingEnabledByUser() {
Brad Ebinger16417b42017-03-07 13:48:50 -0800290 // If user can't edit Enhanced 4G LTE Mode, it assumes Enhanced 4G LTE Mode is always true.
291 // If user changes SIM from editable mode to uneditable mode, need to return true.
Malcolm Chen212ca652017-09-28 17:28:45 -0700292 if (!getBooleanCarrierConfig(CarrierConfigManager.KEY_EDITABLE_ENHANCED_4G_LTE_BOOL)) {
Brad Ebinger16417b42017-03-07 13:48:50 -0800293 return true;
294 }
Malcolm Chen212ca652017-09-28 17:28:45 -0700295
296 int setting = SubscriptionManager.getIntegerSubscriptionProperty(
297 getSubId(), SubscriptionManager.ENHANCED_4G_MODE_ENABLED,
298 SUB_PROPERTY_NOT_INITIALIZED, mContext);
299
300 // If it's never set, by default we return true.
301 return (setting == SUB_PROPERTY_NOT_INITIALIZED || setting == 1);
Brad Ebinger16417b42017-03-07 13:48:50 -0800302 }
303
304 /**
305 * Change persistent Enhanced 4G LTE Mode setting.
306 *
Brad Ebingeref267192017-08-28 13:19:22 -0700307 * @deprecated Doesn't support MSIM devices. Use {@link #setEnhanced4gLteModeSetting(boolean)}
Brad Ebinger16417b42017-03-07 13:48:50 -0800308 * instead.
Etan Cohen82f78122014-12-15 10:10:14 -0800309 */
310 public static void setEnhanced4gLteModeSetting(Context context, boolean enabled) {
Brad Ebingeref267192017-08-28 13:19:22 -0700311 ImsManager mgr = ImsManager.getInstance(context,
312 SubscriptionManager.getDefaultVoicePhoneId());
313 if (mgr != null) {
314 mgr.setEnhanced4gLteModeSetting(enabled);
Etan Cohen82f78122014-12-15 10:10:14 -0800315 }
Brad Ebingeref267192017-08-28 13:19:22 -0700316 loge("setEnhanced4gLteModeSetting: ImsManager null, value not set.");
Etan Cohen82f78122014-12-15 10:10:14 -0800317 }
318
319 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800320 * Change persistent Enhanced 4G LTE Mode setting. If the the option is not editable
321 * ({@link CarrierConfigManager#KEY_EDITABLE_ENHANCED_4G_LTE_BOOL} is false), this method will
322 * always set the setting to true.
323 *
324 */
Brad Ebingeref267192017-08-28 13:19:22 -0700325 public void setEnhanced4gLteModeSetting(boolean enabled) {
Malcolm Chen212ca652017-09-28 17:28:45 -0700326 // If false, we must always keep advanced 4G mode set to true.
327 enabled = getBooleanCarrierConfig(CarrierConfigManager.KEY_EDITABLE_ENHANCED_4G_LTE_BOOL)
328 ? enabled : true;
Brad Ebinger16417b42017-03-07 13:48:50 -0800329
Malcolm Chen212ca652017-09-28 17:28:45 -0700330 int prevSetting = SubscriptionManager.getIntegerSubscriptionProperty(
331 getSubId(), SubscriptionManager.ENHANCED_4G_MODE_ENABLED,
332 SUB_PROPERTY_NOT_INITIALIZED, mContext);
Brad Ebinger16417b42017-03-07 13:48:50 -0800333
Malcolm Chen212ca652017-09-28 17:28:45 -0700334 if (prevSetting != (enabled ? 1 : 0)) {
335 SubscriptionManager.setSubscriptionProperty(getSubId(),
336 SubscriptionManager.ENHANCED_4G_MODE_ENABLED, booleanToPropertyString(enabled));
337 if (isNonTtyOrTtyOnVolteEnabled()) {
338 try {
339 setAdvanced4GMode(enabled);
340 } catch (ImsException ie) {
341 // do nothing
342 }
Brad Ebinger16417b42017-03-07 13:48:50 -0800343 }
344 }
345 }
346
347 /**
Etan Cohen82f78122014-12-15 10:10:14 -0800348 * Indicates whether the call is non-TTY or if TTY - whether TTY on VoLTE is
349 * supported.
Brad Ebinger16417b42017-03-07 13:48:50 -0800350 * @deprecated Does not support MSIM devices. Please use
Brad Ebingeref267192017-08-28 13:19:22 -0700351 * {@link #isNonTtyOrTtyOnVolteEnabled()} instead.
Etan Cohen82f78122014-12-15 10:10:14 -0800352 */
353 public static boolean isNonTtyOrTtyOnVolteEnabled(Context context) {
Brad Ebingeref267192017-08-28 13:19:22 -0700354 ImsManager mgr = ImsManager.getInstance(context,
355 SubscriptionManager.getDefaultVoicePhoneId());
356 if (mgr != null) {
357 return mgr.isNonTtyOrTtyOnVolteEnabled();
358 }
359 loge("isNonTtyOrTtyOnVolteEnabled: ImsManager null, returning default value.");
360 return false;
361 }
362
363 /**
364 * Indicates whether the call is non-TTY or if TTY - whether TTY on VoLTE is
365 * supported on a per slot basis.
366 */
367 public boolean isNonTtyOrTtyOnVolteEnabled() {
368 if (getBooleanCarrierConfig(
fionaxu5803ef02016-03-08 11:48:48 -0800369 CarrierConfigManager.KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL)) {
Etan Cohen82f78122014-12-15 10:10:14 -0800370 return true;
371 }
372
Brad Ebingeref267192017-08-28 13:19:22 -0700373 TelecomManager tm = (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
Hall Liue511a202017-08-17 15:49:58 -0700374 if (tm == null) {
375 Log.w(TAG, "isNonTtyOrTtyOnVolteEnabled: telecom not available");
376 return true;
377 }
378 return tm.getCurrentTtyMode() == TelecomManager.TTY_MODE_OFF;
Etan Cohen82f78122014-12-15 10:10:14 -0800379 }
380
381 /**
Etan Cohenea2b5832014-10-23 18:50:35 -0700382 * Returns a platform configuration for VoLTE which may override the user setting.
Brad Ebinger16417b42017-03-07 13:48:50 -0800383 * @deprecated Does not support MSIM devices. Please use
Brad Ebingeref267192017-08-28 13:19:22 -0700384 * {@link #isVolteEnabledByPlatform()} instead.
Etan Cohen45b5f312014-08-19 15:55:08 -0700385 */
Etan Cohenea2b5832014-10-23 18:50:35 -0700386 public static boolean isVolteEnabledByPlatform(Context context) {
Brad Ebingeref267192017-08-28 13:19:22 -0700387 ImsManager mgr = ImsManager.getInstance(context,
388 SubscriptionManager.getDefaultVoicePhoneId());
389 if (mgr != null) {
390 return mgr.isVolteEnabledByPlatform();
Etan Cohenaf55a402014-09-04 22:34:41 -0700391 }
Brad Ebingeref267192017-08-28 13:19:22 -0700392 loge("isVolteEnabledByPlatform: ImsManager null, returning default value.");
393 return false;
Etan Cohenb5388a32014-11-26 11:57:47 -0800394 }
395
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700396 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800397 * Returns a platform configuration for VoLTE which may override the user setting on a per Slot
398 * basis.
399 */
Brad Ebingeref267192017-08-28 13:19:22 -0700400 public boolean isVolteEnabledByPlatform() {
Brad Ebinger16417b42017-03-07 13:48:50 -0800401 if (SystemProperties.getInt(PROPERTY_DBG_VOLTE_AVAIL_OVERRIDE,
402 PROPERTY_DBG_VOLTE_AVAIL_OVERRIDE_DEFAULT) == 1) {
403 return true;
404 }
405
406 return mContext.getResources().getBoolean(
407 com.android.internal.R.bool.config_device_volte_available)
Malcolm Chen212ca652017-09-28 17:28:45 -0700408 && getBooleanCarrierConfig(CarrierConfigManager.KEY_CARRIER_VOLTE_AVAILABLE_BOOL)
Brad Ebingeref267192017-08-28 13:19:22 -0700409 && isGbaValid();
Brad Ebinger16417b42017-03-07 13:48:50 -0800410 }
411
412 /**
413 * Indicates whether VoLTE is provisioned on device.
414 *
415 * @deprecated Does not support MSIM devices. Please use
Brad Ebingeref267192017-08-28 13:19:22 -0700416 * {@link #isVolteProvisionedOnDevice()} instead.
Etan Cohenb5388a32014-11-26 11:57:47 -0800417 */
418 public static boolean isVolteProvisionedOnDevice(Context context) {
Brad Ebingeref267192017-08-28 13:19:22 -0700419 ImsManager mgr = ImsManager.getInstance(context,
420 SubscriptionManager.getDefaultVoicePhoneId());
421 if (mgr != null) {
422 return mgr.isVolteProvisionedOnDevice();
Etan Cohenb5388a32014-11-26 11:57:47 -0800423 }
Brad Ebingeref267192017-08-28 13:19:22 -0700424 loge("isVolteProvisionedOnDevice: ImsManager null, returning default value.");
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700425 return true;
426 }
427
428 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800429 * Indicates whether VoLTE is provisioned on this slot.
430 */
Brad Ebingeref267192017-08-28 13:19:22 -0700431 public boolean isVolteProvisionedOnDevice() {
432 if (getBooleanCarrierConfig(
Brad Ebinger16417b42017-03-07 13:48:50 -0800433 CarrierConfigManager.KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL)) {
434 return isVolteProvisioned();
435 }
436
437 return true;
438 }
439
440 /**
Meng Wang54fd41a2017-04-12 11:44:47 -0700441 * Indicates whether VoWifi is provisioned on device.
442 *
443 * When CarrierConfig KEY_CARRIER_VOLTE_OVERRIDE_WFC_PROVISIONING_BOOL is true, and VoLTE is not
444 * provisioned on device, this method returns false.
Brad Ebinger16417b42017-03-07 13:48:50 -0800445 *
446 * @deprecated Does not support MSIM devices. Please use
Brad Ebingeref267192017-08-28 13:19:22 -0700447 * {@link #isWfcProvisionedOnDevice()} instead.
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700448 */
449 public static boolean isWfcProvisionedOnDevice(Context context) {
Brad Ebingeref267192017-08-28 13:19:22 -0700450 ImsManager mgr = ImsManager.getInstance(context,
451 SubscriptionManager.getDefaultVoicePhoneId());
452 if (mgr != null) {
453 return mgr.isWfcProvisionedOnDevice();
Meng Wang54fd41a2017-04-12 11:44:47 -0700454 }
Brad Ebingeref267192017-08-28 13:19:22 -0700455 loge("isWfcProvisionedOnDevice: ImsManager null, returning default value.");
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700456 return true;
457 }
458
459 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800460 * Indicates whether VoWifi is provisioned on slot.
Meng Wang54fd41a2017-04-12 11:44:47 -0700461 *
462 * When CarrierConfig KEY_CARRIER_VOLTE_OVERRIDE_WFC_PROVISIONING_BOOL is true, and VoLTE is not
463 * provisioned on device, this method returns false.
Brad Ebinger16417b42017-03-07 13:48:50 -0800464 */
Brad Ebingeref267192017-08-28 13:19:22 -0700465 public boolean isWfcProvisionedOnDevice() {
466 if (getBooleanCarrierConfig(
Meng Wang54fd41a2017-04-12 11:44:47 -0700467 CarrierConfigManager.KEY_CARRIER_VOLTE_OVERRIDE_WFC_PROVISIONING_BOOL)) {
Brad Ebingeref267192017-08-28 13:19:22 -0700468 if (!isVolteProvisionedOnDevice()) {
Meng Wang54fd41a2017-04-12 11:44:47 -0700469 return false;
470 }
471 }
472
Brad Ebingeref267192017-08-28 13:19:22 -0700473 if (getBooleanCarrierConfig(
Brad Ebinger16417b42017-03-07 13:48:50 -0800474 CarrierConfigManager.KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL)) {
Meng Wang54fd41a2017-04-12 11:44:47 -0700475 return isWfcProvisioned();
Brad Ebinger16417b42017-03-07 13:48:50 -0800476 }
477
478 return true;
479 }
480
481 /**
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700482 * Indicates whether VT is provisioned on device
Brad Ebinger16417b42017-03-07 13:48:50 -0800483 *
484 * @deprecated Does not support MSIM devices. Please use
Brad Ebingeref267192017-08-28 13:19:22 -0700485 * {@link #isVtProvisionedOnDevice()} instead.
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700486 */
487 public static boolean isVtProvisionedOnDevice(Context context) {
Brad Ebingeref267192017-08-28 13:19:22 -0700488 ImsManager mgr = ImsManager.getInstance(context,
489 SubscriptionManager.getDefaultVoicePhoneId());
490 if (mgr != null) {
491 return mgr.isVtProvisionedOnDevice();
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700492 }
Brad Ebingeref267192017-08-28 13:19:22 -0700493 loge("isVtProvisionedOnDevice: ImsManager null, returning default value.");
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700494 return true;
Etan Cohenb651fa52014-10-22 10:51:29 -0700495 }
496
Etan Cohenea2b5832014-10-23 18:50:35 -0700497 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800498 * Indicates whether VT is provisioned on slot.
499 */
Brad Ebingeref267192017-08-28 13:19:22 -0700500 public boolean isVtProvisionedOnDevice() {
501 if (getBooleanCarrierConfig(
Brad Ebinger16417b42017-03-07 13:48:50 -0800502 CarrierConfigManager.KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL)) {
503 return isVtProvisioned();
504 }
505
506 return true;
507 }
508
509 /**
Etan Cohenea2b5832014-10-23 18:50:35 -0700510 * Returns a platform configuration for VT which may override the user setting.
511 *
512 * Note: VT presumes that VoLTE is enabled (these are configuration settings
513 * which must be done correctly).
Brad Ebinger16417b42017-03-07 13:48:50 -0800514 *
515 * @deprecated Does not support MSIM devices. Please use
Brad Ebingeref267192017-08-28 13:19:22 -0700516 * {@link #isVtEnabledByPlatform()} instead.
Etan Cohenea2b5832014-10-23 18:50:35 -0700517 */
Etan Cohenb651fa52014-10-22 10:51:29 -0700518 public static boolean isVtEnabledByPlatform(Context context) {
Brad Ebingeref267192017-08-28 13:19:22 -0700519 ImsManager mgr = ImsManager.getInstance(context,
520 SubscriptionManager.getDefaultVoicePhoneId());
521 if (mgr != null) {
522 return mgr.isVtEnabledByPlatform();
Etan Cohenea2b5832014-10-23 18:50:35 -0700523 }
Brad Ebingeref267192017-08-28 13:19:22 -0700524 loge("isVtEnabledByPlatform: ImsManager null, returning default value.");
525 return false;
Etan Cohen45b5f312014-08-19 15:55:08 -0700526 }
527
Etan Cohena00c9192014-12-23 15:02:29 -0800528 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800529 * Returns a platform configuration for VT which may override the user setting.
530 *
531 * Note: VT presumes that VoLTE is enabled (these are configuration settings
532 * which must be done correctly).
533 */
Brad Ebingeref267192017-08-28 13:19:22 -0700534 public boolean isVtEnabledByPlatform() {
Brad Ebinger16417b42017-03-07 13:48:50 -0800535 if (SystemProperties.getInt(PROPERTY_DBG_VT_AVAIL_OVERRIDE,
536 PROPERTY_DBG_VT_AVAIL_OVERRIDE_DEFAULT) == 1) {
537 return true;
538 }
539
540 return mContext.getResources().getBoolean(
541 com.android.internal.R.bool.config_device_vt_available) &&
Malcolm Chen212ca652017-09-28 17:28:45 -0700542 getBooleanCarrierConfig(CarrierConfigManager.KEY_CARRIER_VT_AVAILABLE_BOOL) &&
Brad Ebingeref267192017-08-28 13:19:22 -0700543 isGbaValid();
Brad Ebinger16417b42017-03-07 13:48:50 -0800544 }
545
546 /**
Etan Cohena7d32e82015-05-04 18:02:09 -0700547 * Returns the user configuration of VT setting
Brad Ebinger16417b42017-03-07 13:48:50 -0800548 * @deprecated Does not support MSIM devices. Please use
Brad Ebingeref267192017-08-28 13:19:22 -0700549 * {@link #isVtEnabledByUser()} instead.
Etan Cohena7d32e82015-05-04 18:02:09 -0700550 */
551 public static boolean isVtEnabledByUser(Context context) {
Brad Ebingeref267192017-08-28 13:19:22 -0700552 ImsManager mgr = ImsManager.getInstance(context,
553 SubscriptionManager.getDefaultVoicePhoneId());
554 if (mgr != null) {
555 return mgr.isVtEnabledByUser();
556 }
557 loge("isVtEnabledByUser: ImsManager null, returning default value.");
558 return false;
Etan Cohena7d32e82015-05-04 18:02:09 -0700559 }
560
561 /**
Malcolm Chen212ca652017-09-28 17:28:45 -0700562 * Returns the user configuration of VT setting per slot. If not set, it
563 * returns true as default value.
Brad Ebinger16417b42017-03-07 13:48:50 -0800564 */
Brad Ebingeref267192017-08-28 13:19:22 -0700565 public boolean isVtEnabledByUser() {
Malcolm Chen212ca652017-09-28 17:28:45 -0700566 int setting = SubscriptionManager.getIntegerSubscriptionProperty(
567 getSubId(), SubscriptionManager.VT_IMS_ENABLED,
568 SUB_PROPERTY_NOT_INITIALIZED, mContext);
569
570 // If it's never set, by default we return true.
571 return (setting == SUB_PROPERTY_NOT_INITIALIZED || setting == 1);
Brad Ebinger16417b42017-03-07 13:48:50 -0800572 }
573
574 /**
Etan Cohena7d32e82015-05-04 18:02:09 -0700575 * Change persistent VT enabled setting
Brad Ebinger16417b42017-03-07 13:48:50 -0800576 *
Brad Ebingeref267192017-08-28 13:19:22 -0700577 * @deprecated Does not support MSIM devices. Please use {@link #setVtSetting(boolean)} instead.
Etan Cohena7d32e82015-05-04 18:02:09 -0700578 */
579 public static void setVtSetting(Context context, boolean enabled) {
Brad Ebingeref267192017-08-28 13:19:22 -0700580 ImsManager mgr = ImsManager.getInstance(context,
Etan Cohena7d32e82015-05-04 18:02:09 -0700581 SubscriptionManager.getDefaultVoicePhoneId());
Brad Ebingeref267192017-08-28 13:19:22 -0700582 if (mgr != null) {
583 mgr.setVtSetting(enabled);
Etan Cohena7d32e82015-05-04 18:02:09 -0700584 }
Brad Ebingeref267192017-08-28 13:19:22 -0700585 loge("setVtSetting: ImsManager null, can not set value.");
Etan Cohena7d32e82015-05-04 18:02:09 -0700586 }
587
Brad Ebinger16417b42017-03-07 13:48:50 -0800588 /**
589 * Change persistent VT enabled setting for slot.
590 */
Brad Ebingeref267192017-08-28 13:19:22 -0700591 public void setVtSetting(boolean enabled) {
Malcolm Chen212ca652017-09-28 17:28:45 -0700592 SubscriptionManager.setSubscriptionProperty(getSubId(),
593 SubscriptionManager.VT_IMS_ENABLED,
594 booleanToPropertyString(enabled));
Brad Ebinger16417b42017-03-07 13:48:50 -0800595 try {
596 ImsConfig config = getConfigInterface();
597 config.setFeatureValue(ImsConfig.FeatureConstants.FEATURE_TYPE_VIDEO_OVER_LTE,
598 TelephonyManager.NETWORK_TYPE_LTE,
599 enabled ? ImsConfig.FeatureValueConstants.ON
600 : ImsConfig.FeatureValueConstants.OFF,
601 mImsConfigListener);
602
603 if (enabled) {
Brad Ebingeref267192017-08-28 13:19:22 -0700604 log("setVtSetting(b) : turnOnIms");
Brad Ebinger16417b42017-03-07 13:48:50 -0800605 turnOnIms();
Brad Ebingeref267192017-08-28 13:19:22 -0700606 } else if (isVolteEnabledByPlatform()
607 && (!isVolteEnabledByPlatform()
608 || !isEnhanced4gLteModeSettingEnabledByUser())) {
609 log("setVtSetting(b) : imsServiceAllowTurnOff -> turnOffIms");
Brad Ebinger16417b42017-03-07 13:48:50 -0800610 turnOffIms();
611 }
612 } catch (ImsException e) {
Brad Ebingeref267192017-08-28 13:19:22 -0700613 loge("setVtSetting(b): ", e);
Brad Ebinger16417b42017-03-07 13:48:50 -0800614 }
615 }
616
617 /**
Meng Wang9352c432016-06-08 14:22:20 -0700618 * Returns whether turning off ims is allowed by platform.
619 * The platform property may override the carrier config.
Brad Ebinger16417b42017-03-07 13:48:50 -0800620 *
621 * @deprecated Does not support MSIM devices. Please use
Brad Ebingeref267192017-08-28 13:19:22 -0700622 * {@link #isTurnOffImsAllowedByPlatform()} instead.
Meng Wang9352c432016-06-08 14:22:20 -0700623 */
624 private static boolean isTurnOffImsAllowedByPlatform(Context context) {
Brad Ebingeref267192017-08-28 13:19:22 -0700625 ImsManager mgr = ImsManager.getInstance(context,
626 SubscriptionManager.getDefaultVoicePhoneId());
627 if (mgr != null) {
628 return mgr.isTurnOffImsAllowedByPlatform();
Meng Wang9352c432016-06-08 14:22:20 -0700629 }
Brad Ebingeref267192017-08-28 13:19:22 -0700630 loge("isTurnOffImsAllowedByPlatform: ImsManager null, returning default value.");
631 return true;
Meng Wang9352c432016-06-08 14:22:20 -0700632 }
633
Etan Cohena7d32e82015-05-04 18:02:09 -0700634 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800635 * Returns whether turning off ims is allowed by platform.
636 * The platform property may override the carrier config.
637 */
Brad Ebingeref267192017-08-28 13:19:22 -0700638 private boolean isTurnOffImsAllowedByPlatform() {
Brad Ebinger16417b42017-03-07 13:48:50 -0800639 if (SystemProperties.getInt(PROPERTY_DBG_ALLOW_IMS_OFF_OVERRIDE,
640 PROPERTY_DBG_ALLOW_IMS_OFF_OVERRIDE_DEFAULT) == 1) {
641 return true;
642 }
Brad Ebingeref267192017-08-28 13:19:22 -0700643 return getBooleanCarrierConfig(
Brad Ebinger16417b42017-03-07 13:48:50 -0800644 CarrierConfigManager.KEY_CARRIER_ALLOW_TURNOFF_IMS_BOOL);
645 }
646
647 /**
Etan Cohena00c9192014-12-23 15:02:29 -0800648 * Returns the user configuration of WFC setting
Brad Ebinger16417b42017-03-07 13:48:50 -0800649 *
650 * @deprecated Does not support MSIM devices. Please use
Brad Ebingeref267192017-08-28 13:19:22 -0700651 * {@link #isWfcEnabledByUser()} instead.
Etan Cohena00c9192014-12-23 15:02:29 -0800652 */
653 public static boolean isWfcEnabledByUser(Context context) {
Brad Ebingeref267192017-08-28 13:19:22 -0700654 ImsManager mgr = ImsManager.getInstance(context,
655 SubscriptionManager.getDefaultVoicePhoneId());
656 if (mgr != null) {
657 return mgr.isWfcEnabledByUser();
658 }
659 loge("isWfcEnabledByUser: ImsManager null, returning default value.");
660 return true;
Etan Cohena00c9192014-12-23 15:02:29 -0800661 }
662
663 /**
Malcolm Chen212ca652017-09-28 17:28:45 -0700664 * Returns the user configuration of WFC setting for slot. If not set, it
665 * queries CarrierConfig value as default.
Brad Ebinger16417b42017-03-07 13:48:50 -0800666 */
Brad Ebingeref267192017-08-28 13:19:22 -0700667 public boolean isWfcEnabledByUser() {
Malcolm Chen212ca652017-09-28 17:28:45 -0700668 int setting = SubscriptionManager.getIntegerSubscriptionProperty(
669 getSubId(), SubscriptionManager.WFC_IMS_ENABLED,
670 SUB_PROPERTY_NOT_INITIALIZED, mContext);
671
672 // SUB_PROPERTY_NOT_INITIALIZED indicates it's never set in sub db.
673 if (setting == SUB_PROPERTY_NOT_INITIALIZED) {
674 return getBooleanCarrierConfig(
675 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ENABLED_BOOL);
676 } else {
677 return setting == 1;
678 }
Brad Ebinger16417b42017-03-07 13:48:50 -0800679 }
680
681 /**
682 * Change persistent WFC enabled setting.
683 * @deprecated Does not support MSIM devices. Please use
Brad Ebingeref267192017-08-28 13:19:22 -0700684 * {@link #setWfcSetting} instead.
Etan Cohena00c9192014-12-23 15:02:29 -0800685 */
686 public static void setWfcSetting(Context context, boolean enabled) {
Brad Ebingeref267192017-08-28 13:19:22 -0700687 ImsManager mgr = ImsManager.getInstance(context,
Etan Cohena00c9192014-12-23 15:02:29 -0800688 SubscriptionManager.getDefaultVoicePhoneId());
Brad Ebingeref267192017-08-28 13:19:22 -0700689 if (mgr != null) {
690 mgr.setWfcSetting(enabled);
Etan Cohena00c9192014-12-23 15:02:29 -0800691 }
Brad Ebingeref267192017-08-28 13:19:22 -0700692 loge("setWfcSetting: ImsManager null, can not set value.");
Etan Cohena00c9192014-12-23 15:02:29 -0800693 }
694
695 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800696 * Change persistent WFC enabled setting for slot.
697 */
Brad Ebingeref267192017-08-28 13:19:22 -0700698 public void setWfcSetting(boolean enabled) {
Malcolm Chen212ca652017-09-28 17:28:45 -0700699 SubscriptionManager.setSubscriptionProperty(getSubId(),
700 SubscriptionManager.WFC_IMS_ENABLED, booleanToPropertyString(enabled));
Brad Ebinger16417b42017-03-07 13:48:50 -0800701
Brad Ebingeref267192017-08-28 13:19:22 -0700702 setWfcNonPersistent(enabled, getWfcMode());
Meng Wang51c09072017-03-27 10:47:45 -0700703 }
704
705 /**
706 * Non-persistently change WFC enabled setting and WFC mode for slot
707 *
708 * @param wfcMode The WFC preference if WFC is enabled
709 */
Brad Ebingeref267192017-08-28 13:19:22 -0700710 public void setWfcNonPersistent(boolean enabled, int wfcMode) {
Meng Wang51c09072017-03-27 10:47:45 -0700711 int imsFeatureValue =
712 enabled ? ImsConfig.FeatureValueConstants.ON : ImsConfig.FeatureValueConstants.OFF;
713 // Force IMS to register over LTE when turning off WFC
714 int imsWfcModeFeatureValue =
715 enabled ? wfcMode : ImsConfig.WfcModeFeatureValueConstants.CELLULAR_PREFERRED;
716
Brad Ebinger16417b42017-03-07 13:48:50 -0800717 try {
718 ImsConfig config = getConfigInterface();
719 config.setFeatureValue(ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_WIFI,
720 TelephonyManager.NETWORK_TYPE_IWLAN,
Meng Wang51c09072017-03-27 10:47:45 -0700721 imsFeatureValue,
Brad Ebinger16417b42017-03-07 13:48:50 -0800722 mImsConfigListener);
723
724 if (enabled) {
Brad Ebingeref267192017-08-28 13:19:22 -0700725 log("setWfcSetting() : turnOnIms");
Brad Ebinger16417b42017-03-07 13:48:50 -0800726 turnOnIms();
Brad Ebingeref267192017-08-28 13:19:22 -0700727 } else if (isTurnOffImsAllowedByPlatform()
728 && (!isVolteEnabledByPlatform()
729 || !isEnhanced4gLteModeSettingEnabledByUser())) {
730 log("setWfcSetting() : imsServiceAllowTurnOff -> turnOffIms");
Brad Ebinger16417b42017-03-07 13:48:50 -0800731 turnOffIms();
732 }
733
Brad Ebingeref267192017-08-28 13:19:22 -0700734 setWfcModeInternal(imsWfcModeFeatureValue);
Brad Ebinger16417b42017-03-07 13:48:50 -0800735 } catch (ImsException e) {
Brad Ebingeref267192017-08-28 13:19:22 -0700736 loge("setWfcSetting(): ", e);
Brad Ebinger16417b42017-03-07 13:48:50 -0800737 }
738 }
739
740 /**
741 * Returns the user configuration of WFC preference setting.
742 *
Malcolm Chen212ca652017-09-28 17:28:45 -0700743 * @deprecated Doesn't support MSIM devices. Use {@link #getWfcMode(boolean roaming)} instead.
Etan Cohena00c9192014-12-23 15:02:29 -0800744 */
745 public static int getWfcMode(Context context) {
Brad Ebingeref267192017-08-28 13:19:22 -0700746 ImsManager mgr = ImsManager.getInstance(context,
747 SubscriptionManager.getDefaultVoicePhoneId());
748 if (mgr != null) {
749 return mgr.getWfcMode();
750 }
751 loge("getWfcMode: ImsManager null, returning default value.");
752 return ImsConfig.WfcModeFeatureValueConstants.WIFI_ONLY;
Etan Cohena00c9192014-12-23 15:02:29 -0800753 }
754
755 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800756 * Returns the user configuration of WFC preference setting
Malcolm Chen212ca652017-09-28 17:28:45 -0700757 * @deprecated. Use {@link #getWfcMode(boolean roaming)} instead.
Brad Ebinger16417b42017-03-07 13:48:50 -0800758 */
Brad Ebingeref267192017-08-28 13:19:22 -0700759 public int getWfcMode() {
Malcolm Chen212ca652017-09-28 17:28:45 -0700760 return getWfcMode(false);
Brad Ebinger16417b42017-03-07 13:48:50 -0800761 }
762
763 /**
764 * Change persistent WFC preference setting.
765 *
Brad Ebingeref267192017-08-28 13:19:22 -0700766 * @deprecated Doesn't support MSIM devices. Use {@link #setWfcMode(int)} instead.
Etan Cohena00c9192014-12-23 15:02:29 -0800767 */
768 public static void setWfcMode(Context context, int wfcMode) {
Brad Ebingeref267192017-08-28 13:19:22 -0700769 ImsManager mgr = ImsManager.getInstance(context,
770 SubscriptionManager.getDefaultVoicePhoneId());
771 if (mgr != null) {
772 mgr.setWfcMode(wfcMode);
773 }
774 loge("setWfcMode: ImsManager null, can not set value.");
Pavel Zhamaitsiak9e6eca22015-03-16 15:30:53 -0700775 }
776
Meng Wang37477012016-09-20 09:59:56 -0700777 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800778 * Change persistent WFC preference setting for slot.
779 */
Brad Ebingeref267192017-08-28 13:19:22 -0700780 public void setWfcMode(int wfcMode) {
781 if (DBG) log("setWfcMode(i) - setting=" + wfcMode);
Malcolm Chen212ca652017-09-28 17:28:45 -0700782
783 SubscriptionManager.setSubscriptionProperty(getSubId(),
784 SubscriptionManager.WFC_IMS_MODE, Integer.toString(wfcMode));
Brad Ebinger16417b42017-03-07 13:48:50 -0800785
Brad Ebingeref267192017-08-28 13:19:22 -0700786 setWfcModeInternal(wfcMode);
Brad Ebinger16417b42017-03-07 13:48:50 -0800787 }
788
789 /**
Suresh Koleti76491082017-04-21 18:39:50 +0530790 * Changes the WFC mode to its default value for Carriers with non-editable WFC settings.
791 */
792 private void updateDefaultWfcMode() {
793 if (DBG) log("updateDefaultWfcMode");
Brad Ebingeref267192017-08-28 13:19:22 -0700794 if (!getBooleanCarrierConfig(CarrierConfigManager.KEY_EDITABLE_WFC_MODE_BOOL)) {
795 setWfcMode(getIntCarrierConfig(
Suresh Koleti76491082017-04-21 18:39:50 +0530796 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_MODE_INT));
797 }
798 }
799
800 /**
Meng Wang37477012016-09-20 09:59:56 -0700801 * Returns the user configuration of WFC preference setting
802 *
803 * @param roaming {@code false} for home network setting, {@code true} for roaming setting
Brad Ebinger16417b42017-03-07 13:48:50 -0800804 *
Brad Ebingeref267192017-08-28 13:19:22 -0700805 * @deprecated Doesn't support MSIM devices. Use {@link #getWfcMode(boolean)} instead.
Meng Wang37477012016-09-20 09:59:56 -0700806 */
807 public static int getWfcMode(Context context, boolean roaming) {
Brad Ebingeref267192017-08-28 13:19:22 -0700808 ImsManager mgr = ImsManager.getInstance(context,
809 SubscriptionManager.getDefaultVoicePhoneId());
810 if (mgr != null) {
811 return mgr.getWfcMode(roaming);
Meng Wang37477012016-09-20 09:59:56 -0700812 }
Brad Ebingeref267192017-08-28 13:19:22 -0700813 loge("getWfcMode: ImsManager null, returning default value.");
814 return ImsConfig.WfcModeFeatureValueConstants.WIFI_ONLY;
Meng Wang37477012016-09-20 09:59:56 -0700815 }
816
817 /**
Malcolm Chen212ca652017-09-28 17:28:45 -0700818 * Returns the user configuration of WFC preference setting for slot. If not set, it
819 * queries CarrierConfig value as default.
Brad Ebinger16417b42017-03-07 13:48:50 -0800820 *
821 * @param roaming {@code false} for home network setting, {@code true} for roaming setting
822 */
Brad Ebingeref267192017-08-28 13:19:22 -0700823 public int getWfcMode(boolean roaming) {
Brad Ebinger16417b42017-03-07 13:48:50 -0800824 int setting = 0;
825 if (!roaming) {
Malcolm Chen212ca652017-09-28 17:28:45 -0700826 setting = SubscriptionManager.getIntegerSubscriptionProperty(
827 getSubId(), SubscriptionManager.WFC_IMS_MODE,
828 SUB_PROPERTY_NOT_INITIALIZED, mContext);
829
830 // SUB_PROPERTY_NOT_INITIALIZED indicates it's never set in sub db.
831 if (setting == SUB_PROPERTY_NOT_INITIALIZED) {
832 setting = getIntCarrierConfig(
833 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_MODE_INT);
834 }
Brad Ebingeref267192017-08-28 13:19:22 -0700835 if (DBG) log("getWfcMode - setting=" + setting);
Brad Ebinger16417b42017-03-07 13:48:50 -0800836 } else {
Malcolm Chen212ca652017-09-28 17:28:45 -0700837 setting = SubscriptionManager.getIntegerSubscriptionProperty(
838 getSubId(), SubscriptionManager.WFC_IMS_ROAMING_MODE,
839 SUB_PROPERTY_NOT_INITIALIZED, mContext);
840
841 // SUB_PROPERTY_NOT_INITIALIZED indicates it's never set in sub db.
842 if (setting == SUB_PROPERTY_NOT_INITIALIZED) {
843 setting = getIntCarrierConfig(
844 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_MODE_INT);
845 }
846
Brad Ebingeref267192017-08-28 13:19:22 -0700847 if (DBG) log("getWfcMode (roaming) - setting=" + setting);
Brad Ebinger16417b42017-03-07 13:48:50 -0800848 }
849 return setting;
850 }
851
852 /**
Meng Wang37477012016-09-20 09:59:56 -0700853 * Change persistent WFC preference setting
854 *
855 * @param roaming {@code false} for home network setting, {@code true} for roaming setting
Brad Ebinger16417b42017-03-07 13:48:50 -0800856 *
Brad Ebingeref267192017-08-28 13:19:22 -0700857 * @deprecated Doesn't support MSIM devices. Please use {@link #setWfcMode(int, boolean)}
858 * instead.
Meng Wang37477012016-09-20 09:59:56 -0700859 */
860 public static void setWfcMode(Context context, int wfcMode, boolean roaming) {
Brad Ebingeref267192017-08-28 13:19:22 -0700861 ImsManager mgr = ImsManager.getInstance(context,
862 SubscriptionManager.getDefaultVoicePhoneId());
863 if (mgr != null) {
864 mgr.setWfcMode(wfcMode, roaming);
Meng Wang37477012016-09-20 09:59:56 -0700865 }
Brad Ebingeref267192017-08-28 13:19:22 -0700866 loge("setWfcMode: ImsManager null, can not set value.");
Meng Wang37477012016-09-20 09:59:56 -0700867 }
868
Brad Ebinger16417b42017-03-07 13:48:50 -0800869 /**
870 * Change persistent WFC preference setting
871 *
872 * @param roaming {@code false} for home network setting, {@code true} for roaming setting
873 */
Brad Ebingeref267192017-08-28 13:19:22 -0700874 public void setWfcMode(int wfcMode, boolean roaming) {
Brad Ebinger16417b42017-03-07 13:48:50 -0800875 if (!roaming) {
Brad Ebingeref267192017-08-28 13:19:22 -0700876 if (DBG) log("setWfcMode(i,b) - setting=" + wfcMode);
Malcolm Chen212ca652017-09-28 17:28:45 -0700877 SubscriptionManager.setSubscriptionProperty(getSubId(),
878 SubscriptionManager.WFC_IMS_MODE, Integer.toString(wfcMode));
Brad Ebinger16417b42017-03-07 13:48:50 -0800879 } else {
Brad Ebingeref267192017-08-28 13:19:22 -0700880 if (DBG) log("setWfcMode(i,b) (roaming) - setting=" + wfcMode);
Malcolm Chen212ca652017-09-28 17:28:45 -0700881 SubscriptionManager.setSubscriptionProperty(getSubId(),
882 SubscriptionManager.WFC_IMS_ROAMING_MODE, Integer.toString(wfcMode));
Brad Ebinger16417b42017-03-07 13:48:50 -0800883 }
884
Brad Ebingeref267192017-08-28 13:19:22 -0700885 TelephonyManager tm = (TelephonyManager)
886 mContext.getSystemService(Context.TELEPHONY_SERVICE);
887 if (roaming == tm.isNetworkRoaming(getSubId())) {
888 setWfcModeInternal(wfcMode);
889 }
890 }
891
892 private int getSubId() {
Brad Ebinger16417b42017-03-07 13:48:50 -0800893 int[] subIds = SubscriptionManager.getSubId(mPhoneId);
894 int subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
895 if (subIds != null && subIds.length >= 1) {
896 subId = subIds[0];
897 }
Brad Ebingeref267192017-08-28 13:19:22 -0700898 return subId;
Brad Ebinger16417b42017-03-07 13:48:50 -0800899 }
900
Pavel Zhamaitsiak9e6eca22015-03-16 15:30:53 -0700901 private static void setWfcModeInternal(Context context, int wfcMode) {
Etan Cohena00c9192014-12-23 15:02:29 -0800902 final ImsManager imsManager = ImsManager.getInstance(context,
903 SubscriptionManager.getDefaultVoicePhoneId());
904 if (imsManager != null) {
905 final int value = wfcMode;
Pavel Zhamaitsiak47aeacf2016-03-30 18:54:55 -0700906 Thread thread = new Thread(new Runnable() {
Etan Cohena00c9192014-12-23 15:02:29 -0800907 public void run() {
908 try {
909 imsManager.getConfigInterface().setProvisionedValue(
910 ImsConfig.ConfigConstants.VOICE_OVER_WIFI_MODE,
911 value);
912 } catch (ImsException e) {
913 // do nothing
914 }
915 }
916 });
Pavel Zhamaitsiak47aeacf2016-03-30 18:54:55 -0700917 thread.start();
Etan Cohena00c9192014-12-23 15:02:29 -0800918 }
919 }
920
Brad Ebingeref267192017-08-28 13:19:22 -0700921 private void setWfcModeInternal(int wfcMode) {
Brad Ebinger16417b42017-03-07 13:48:50 -0800922 final int value = wfcMode;
923 Thread thread = new Thread(() -> {
Malcolm Chen212ca652017-09-28 17:28:45 -0700924 try {
925 getConfigInterface().setProvisionedValue(
926 ImsConfig.ConfigConstants.VOICE_OVER_WIFI_MODE, value);
927 } catch (ImsException e) {
928 // do nothing
929 }
Brad Ebinger16417b42017-03-07 13:48:50 -0800930 });
931 thread.start();
932 }
933
Etan Cohena00c9192014-12-23 15:02:29 -0800934 /**
935 * Returns the user configuration of WFC roaming setting
Brad Ebinger16417b42017-03-07 13:48:50 -0800936 *
937 * @deprecated Does not support MSIM devices. Please use
Brad Ebingeref267192017-08-28 13:19:22 -0700938 * {@link #isWfcRoamingEnabledByUser()} instead.
Etan Cohena00c9192014-12-23 15:02:29 -0800939 */
940 public static boolean isWfcRoamingEnabledByUser(Context context) {
Brad Ebingeref267192017-08-28 13:19:22 -0700941 ImsManager mgr = ImsManager.getInstance(context,
942 SubscriptionManager.getDefaultVoicePhoneId());
943 if (mgr != null) {
944 return mgr.isWfcRoamingEnabledByUser();
945 }
946 loge("isWfcRoamingEnabledByUser: ImsManager null, returning default value.");
947 return false;
Etan Cohena00c9192014-12-23 15:02:29 -0800948 }
949
950 /**
Malcolm Chen212ca652017-09-28 17:28:45 -0700951 * Returns the user configuration of WFC roaming setting for slot. If not set, it
952 * queries CarrierConfig value as default.
Brad Ebinger16417b42017-03-07 13:48:50 -0800953 */
Brad Ebingeref267192017-08-28 13:19:22 -0700954 public boolean isWfcRoamingEnabledByUser() {
Malcolm Chen212ca652017-09-28 17:28:45 -0700955 int setting = SubscriptionManager.getIntegerSubscriptionProperty(
956 getSubId(), SubscriptionManager.WFC_IMS_ROAMING_ENABLED,
957 SUB_PROPERTY_NOT_INITIALIZED, mContext);
958 if (setting == SUB_PROPERTY_NOT_INITIALIZED) {
959 return getBooleanCarrierConfig(
960 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_ENABLED_BOOL);
961 } else {
962 return (setting == 1);
963 }
Brad Ebinger16417b42017-03-07 13:48:50 -0800964 }
965
966 /**
Etan Cohena00c9192014-12-23 15:02:29 -0800967 * Change persistent WFC roaming enabled setting
968 */
969 public static void setWfcRoamingSetting(Context context, boolean enabled) {
Brad Ebingeref267192017-08-28 13:19:22 -0700970 ImsManager mgr = ImsManager.getInstance(context,
Etan Cohena00c9192014-12-23 15:02:29 -0800971 SubscriptionManager.getDefaultVoicePhoneId());
Brad Ebingeref267192017-08-28 13:19:22 -0700972 if (mgr != null) {
973 mgr.setWfcRoamingSetting(enabled);
Etan Cohena00c9192014-12-23 15:02:29 -0800974 }
Brad Ebingeref267192017-08-28 13:19:22 -0700975 loge("setWfcRoamingSetting: ImsManager null, value not set.");
Etan Cohena00c9192014-12-23 15:02:29 -0800976 }
977
978 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800979 * Change persistent WFC roaming enabled setting
980 */
Brad Ebingeref267192017-08-28 13:19:22 -0700981 public void setWfcRoamingSetting(boolean enabled) {
Malcolm Chen212ca652017-09-28 17:28:45 -0700982 SubscriptionManager.setSubscriptionProperty(getSubId(),
983 SubscriptionManager.WFC_IMS_ROAMING_ENABLED, booleanToPropertyString(enabled)
984 );
Brad Ebinger16417b42017-03-07 13:48:50 -0800985
986 setWfcRoamingSettingInternal(enabled);
987 }
988
989 private void setWfcRoamingSettingInternal(boolean enabled) {
990 final int value = enabled
991 ? ImsConfig.FeatureValueConstants.ON
992 : ImsConfig.FeatureValueConstants.OFF;
993 Thread thread = new Thread(() -> {
Malcolm Chen212ca652017-09-28 17:28:45 -0700994 try {
995 getConfigInterface().setProvisionedValue(
996 ImsConfig.ConfigConstants.VOICE_OVER_WIFI_ROAMING, value);
997 } catch (ImsException e) {
998 // do nothing
999 }
Brad Ebinger16417b42017-03-07 13:48:50 -08001000 });
1001 thread.start();
1002 }
1003
1004 /**
Etan Cohena00c9192014-12-23 15:02:29 -08001005 * Returns a platform configuration for WFC which may override the user
1006 * setting. Note: WFC presumes that VoLTE is enabled (these are
1007 * configuration settings which must be done correctly).
Brad Ebinger16417b42017-03-07 13:48:50 -08001008 *
Brad Ebingeref267192017-08-28 13:19:22 -07001009 * @deprecated Doesn't work for MSIM devices. Use {@link #isWfcEnabledByPlatform()}
Brad Ebinger16417b42017-03-07 13:48:50 -08001010 * instead.
Etan Cohena00c9192014-12-23 15:02:29 -08001011 */
1012 public static boolean isWfcEnabledByPlatform(Context context) {
Brad Ebingeref267192017-08-28 13:19:22 -07001013 ImsManager mgr = ImsManager.getInstance(context,
1014 SubscriptionManager.getDefaultVoicePhoneId());
1015 if (mgr != null) {
1016 return mgr.isWfcEnabledByPlatform();
Etan Cohena00c9192014-12-23 15:02:29 -08001017 }
Brad Ebingeref267192017-08-28 13:19:22 -07001018 loge("isWfcEnabledByPlatform: ImsManager null, returning default value.");
1019 return false;
Pavel Zhamaitsiak57911d12015-10-20 14:26:34 -07001020 }
1021
1022 /**
Brad Ebinger16417b42017-03-07 13:48:50 -08001023 * Returns a platform configuration for WFC which may override the user
1024 * setting per slot. Note: WFC presumes that VoLTE is enabled (these are
1025 * configuration settings which must be done correctly).
1026 */
Brad Ebingeref267192017-08-28 13:19:22 -07001027 public boolean isWfcEnabledByPlatform() {
Brad Ebinger16417b42017-03-07 13:48:50 -08001028 if (SystemProperties.getInt(PROPERTY_DBG_WFC_AVAIL_OVERRIDE,
1029 PROPERTY_DBG_WFC_AVAIL_OVERRIDE_DEFAULT) == 1) {
1030 return true;
1031 }
1032
1033 return mContext.getResources().getBoolean(
1034 com.android.internal.R.bool.config_device_wfc_ims_available) &&
Brad Ebingeref267192017-08-28 13:19:22 -07001035 getBooleanCarrierConfig(
Brad Ebinger16417b42017-03-07 13:48:50 -08001036 CarrierConfigManager.KEY_CARRIER_WFC_IMS_AVAILABLE_BOOL) &&
Brad Ebingeref267192017-08-28 13:19:22 -07001037 isGbaValid();
Etan Cohena00c9192014-12-23 15:02:29 -08001038 }
1039
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001040 /**
Brad Ebinger16417b42017-03-07 13:48:50 -08001041 * If carrier requires that IMS is only available if GBA capable SIM is used,
1042 * then this function checks GBA bit in EF IST.
1043 *
1044 * Format of EF IST is defined in 3GPP TS 31.103 (Section 4.2.7).
1045 */
Brad Ebingeref267192017-08-28 13:19:22 -07001046 private boolean isGbaValid() {
1047 if (getBooleanCarrierConfig(
Brad Ebinger16417b42017-03-07 13:48:50 -08001048 CarrierConfigManager.KEY_CARRIER_IMS_GBA_REQUIRED_BOOL)) {
Brad Ebingeref267192017-08-28 13:19:22 -07001049 final TelephonyManager telephonyManager = new TelephonyManager(mContext, getSubId());
Brad Ebinger16417b42017-03-07 13:48:50 -08001050 String efIst = telephonyManager.getIsimIst();
1051 if (efIst == null) {
Brad Ebingeref267192017-08-28 13:19:22 -07001052 loge("isGbaValid - ISF is NULL");
Brad Ebinger16417b42017-03-07 13:48:50 -08001053 return true;
1054 }
1055 boolean result = efIst != null && efIst.length() > 1 &&
1056 (0x02 & (byte)efIst.charAt(1)) != 0;
Brad Ebingeref267192017-08-28 13:19:22 -07001057 if (DBG) log("isGbaValid - GBA capable=" + result + ", ISF=" + efIst);
Brad Ebinger16417b42017-03-07 13:48:50 -08001058 return result;
1059 }
1060 return true;
1061 }
1062
1063 /**
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -07001064 * This function should be called when ImsConfig.ACTION_IMS_CONFIG_CHANGED is received.
1065 *
1066 * We cannot register receiver in ImsManager because this would lead to resource leak.
1067 * ImsManager can be created in different processes and it is not notified when that process
1068 * is about to be terminated.
1069 *
1070 * @hide
1071 * */
1072 public static void onProvisionedValueChanged(Context context, int item, String value) {
Amit Mahajan24f7b162016-07-21 16:33:53 -07001073 if (DBG) Rlog.d(TAG, "onProvisionedValueChanged: item=" + item + " val=" + value);
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -07001074 ImsManager mgr = ImsManager.getInstance(context,
1075 SubscriptionManager.getDefaultVoicePhoneId());
1076
1077 switch (item) {
1078 case ImsConfig.ConfigConstants.VLT_SETTING_ENABLED:
Amit Mahajan24f7b162016-07-21 16:33:53 -07001079 mgr.setVolteProvisionedProperty(value.equals("1"));
1080 if (DBG) Rlog.d(TAG,"isVoLteProvisioned = " + mgr.isVolteProvisioned());
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -07001081 break;
1082
1083 case ImsConfig.ConfigConstants.VOICE_OVER_WIFI_SETTING_ENABLED:
Amit Mahajan24f7b162016-07-21 16:33:53 -07001084 mgr.setWfcProvisionedProperty(value.equals("1"));
1085 if (DBG) Rlog.d(TAG,"isWfcProvisioned = " + mgr.isWfcProvisioned());
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -07001086 break;
1087
Nathan Harolda9fc7f12016-06-30 16:12:14 -07001088 case ImsConfig.ConfigConstants.LVC_SETTING_ENABLED:
Amit Mahajan24f7b162016-07-21 16:33:53 -07001089 mgr.setVtProvisionedProperty(value.equals("1"));
1090 if (DBG) Rlog.d(TAG,"isVtProvisioned = " + mgr.isVtProvisioned());
Nathan Harolda9fc7f12016-06-30 16:12:14 -07001091 break;
1092
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -07001093 }
1094 }
1095
Brad Ebingerbe6cb672017-08-25 14:55:00 -07001096 private class AsyncUpdateProvisionedValues extends AsyncTask<Void, Void, Boolean> {
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -07001097 @Override
Brad Ebingerbe6cb672017-08-25 14:55:00 -07001098 protected Boolean doInBackground(Void... params) {
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -07001099 // disable on any error
Amit Mahajan24f7b162016-07-21 16:33:53 -07001100 setVolteProvisionedProperty(false);
1101 setWfcProvisionedProperty(false);
1102 setVtProvisionedProperty(false);
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -07001103
1104 try {
1105 ImsConfig config = getConfigInterface();
1106 if (config != null) {
Amit Mahajan24f7b162016-07-21 16:33:53 -07001107 setVolteProvisionedProperty(getProvisionedBool(config,
1108 ImsConfig.ConfigConstants.VLT_SETTING_ENABLED));
1109 if (DBG) Rlog.d(TAG, "isVoLteProvisioned = " + isVolteProvisioned());
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -07001110
Amit Mahajan24f7b162016-07-21 16:33:53 -07001111 setWfcProvisionedProperty(getProvisionedBool(config,
1112 ImsConfig.ConfigConstants.VOICE_OVER_WIFI_SETTING_ENABLED));
1113 if (DBG) Rlog.d(TAG, "isWfcProvisioned = " + isWfcProvisioned());
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -07001114
Amit Mahajan24f7b162016-07-21 16:33:53 -07001115 setVtProvisionedProperty(getProvisionedBool(config,
1116 ImsConfig.ConfigConstants.LVC_SETTING_ENABLED));
1117 if (DBG) Rlog.d(TAG, "isVtProvisioned = " + isVtProvisioned());
Nathan Harolda9fc7f12016-06-30 16:12:14 -07001118
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -07001119 }
1120 } catch (ImsException ie) {
Meng Wangca7d4c42016-06-30 22:05:24 -07001121 Rlog.e(TAG, "AsyncUpdateProvisionedValues error: ", ie);
Brad Ebingerbe6cb672017-08-25 14:55:00 -07001122 return false;
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -07001123 }
1124
Brad Ebingerbe6cb672017-08-25 14:55:00 -07001125 return true;
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -07001126 }
1127
Brad Ebingerbe6cb672017-08-25 14:55:00 -07001128 @Override
1129 protected void onPostExecute(Boolean completed) {
1130 if (mProvisionBackoff == null) {
1131 return;
1132 }
1133 if (!completed) {
1134 mProvisionBackoff.notifyFailed();
1135 } else {
1136 mProvisionBackoff.stop();
1137 }
1138 }
1139
1140 /**
1141 * Will return with config value or throw an ImsException if we receive an error from
1142 * ImsConfig for that value.
1143 */
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -07001144 private boolean getProvisionedBool(ImsConfig config, int item) throws ImsException {
Brad Ebingerbe6cb672017-08-25 14:55:00 -07001145 int value = config.getProvisionedValue(item);
1146 if (value == ImsConfig.FeatureValueConstants.ERROR) {
1147 throw new ImsException("getProvisionedBool failed with error for item: " + item,
1148 ImsReasonInfo.CODE_LOCAL_INTERNAL_ERROR);
1149 }
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -07001150 return config.getProvisionedValue(item) == ImsConfig.FeatureValueConstants.ON;
1151 }
1152 }
1153
Brad Ebingerbe6cb672017-08-25 14:55:00 -07001154 // used internally only, use #updateProvisionedValues instead.
1155 private void handleUpdateProvisionedValues() {
Brad Ebingeref267192017-08-28 13:19:22 -07001156 if (getBooleanCarrierConfig(
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -07001157 CarrierConfigManager.KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL)) {
1158
1159 new AsyncUpdateProvisionedValues().execute();
1160 }
1161 }
1162
1163 /**
Brad Ebingerbe6cb672017-08-25 14:55:00 -07001164 * Asynchronously get VoLTE, WFC, VT provisioning statuses. If ImsConfig is not available, we
1165 * will retry with exponential backoff.
1166 */
1167 private void updateProvisionedValues() {
1168 // Start trying to receive provisioning status after BACKOFF_INITIAL_DELAY_MS.
1169 if (mProvisionBackoff != null) {
1170 mProvisionBackoff.start();
1171 } else {
1172 // bypass and launch async thread once without backoff.
1173 handleUpdateProvisionedValues();
1174 }
1175 }
1176
1177 /**
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001178 * Sync carrier config and user settings with ImsConfig.
1179 *
1180 * @param context for the manager object
1181 * @param phoneId phone id
1182 * @param force update
Brad Ebinger16417b42017-03-07 13:48:50 -08001183 *
Brad Ebingeref267192017-08-28 13:19:22 -07001184 * @deprecated Doesn't support MSIM devices. Use {@link #updateImsServiceConfig(boolean)}
1185 * instead.
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001186 */
1187 public static void updateImsServiceConfig(Context context, int phoneId, boolean force) {
Brad Ebingeref267192017-08-28 13:19:22 -07001188 ImsManager mgr = ImsManager.getInstance(context, phoneId);
1189 if (mgr != null) {
1190 mgr.updateImsServiceConfig(force);
Pavel Zhamaitsiakfc202992016-03-29 18:07:38 -07001191 }
Brad Ebingeref267192017-08-28 13:19:22 -07001192 loge("updateImsServiceConfig: ImsManager null, returning without update.");
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001193 }
1194
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -07001195 /**
Brad Ebinger16417b42017-03-07 13:48:50 -08001196 * Sync carrier config and user settings with ImsConfig.
1197 *
1198 * @param context for the manager object
1199 * @param phoneId phone id
1200 * @param force update
1201 */
Brad Ebingeref267192017-08-28 13:19:22 -07001202 public void updateImsServiceConfig(boolean force) {
Brad Ebinger16417b42017-03-07 13:48:50 -08001203 if (!force) {
Brad Ebingeref267192017-08-28 13:19:22 -07001204 TelephonyManager tm = new TelephonyManager(mContext, getSubId());
1205 if (tm.getSimState() != TelephonyManager.SIM_STATE_READY) {
1206 log("updateImsServiceConfig: SIM not ready");
Brad Ebinger16417b42017-03-07 13:48:50 -08001207 // Don't disable IMS if SIM is not ready
1208 return;
1209 }
1210 }
1211
1212 if (!mConfigUpdated || force) {
1213 try {
1214 updateProvisionedValues();
1215
1216 // TODO: Extend ImsConfig API and set all feature values in single function call.
1217
1218 // Note: currently the order of updates is set to produce different order of
1219 // setFeatureValue() function calls from setAdvanced4GMode(). This is done to
1220 // differentiate this code path from vendor code perspective.
1221 boolean isImsUsed = updateVolteFeatureValue();
1222 isImsUsed |= updateWfcFeatureAndProvisionedValues();
1223 isImsUsed |= updateVideoCallFeatureValue();
1224
Brad Ebingeref267192017-08-28 13:19:22 -07001225 if (isImsUsed || !isTurnOffImsAllowedByPlatform()) {
Brad Ebinger16417b42017-03-07 13:48:50 -08001226 // Turn on IMS if it is used.
1227 // Also, if turning off is not allowed for current carrier,
1228 // we need to turn IMS on because it might be turned off before
1229 // phone switched to current carrier.
Brad Ebingeref267192017-08-28 13:19:22 -07001230 log("updateImsServiceConfig: turnOnIms");
Brad Ebinger16417b42017-03-07 13:48:50 -08001231 turnOnIms();
1232 } else {
1233 // Turn off IMS if it is not used AND turning off is allowed for carrier.
Brad Ebingeref267192017-08-28 13:19:22 -07001234 log("updateImsServiceConfig: turnOffIms");
Brad Ebinger16417b42017-03-07 13:48:50 -08001235 turnOffIms();
1236 }
1237
1238 mConfigUpdated = true;
1239 } catch (ImsException e) {
Brad Ebingeref267192017-08-28 13:19:22 -07001240 loge("updateImsServiceConfig: ", e);
Brad Ebinger16417b42017-03-07 13:48:50 -08001241 mConfigUpdated = false;
1242 }
1243 }
1244 }
1245
1246 /**
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -07001247 * Update VoLTE config
1248 * @return whether feature is On
1249 * @throws ImsException
1250 */
1251 private boolean updateVolteFeatureValue() throws ImsException {
Brad Ebingeref267192017-08-28 13:19:22 -07001252 boolean available = isVolteEnabledByPlatform();
1253 boolean enabled = isEnhanced4gLteModeSettingEnabledByUser();
1254 boolean isNonTty = isNonTtyOrTtyOnVolteEnabled();
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -08001255 boolean isFeatureOn = available && enabled && isNonTty;
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001256
1257 log("updateVolteFeatureValue: available = " + available
1258 + ", enabled = " + enabled
1259 + ", nonTTY = " + isNonTty);
1260
1261 getConfigInterface().setFeatureValue(
1262 ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_LTE,
1263 TelephonyManager.NETWORK_TYPE_LTE,
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -08001264 isFeatureOn ?
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001265 ImsConfig.FeatureValueConstants.ON :
1266 ImsConfig.FeatureValueConstants.OFF,
Pavel Zhamaitsiakf4b90322016-01-26 14:34:09 -08001267 mImsConfigListener);
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -07001268
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -08001269 return isFeatureOn;
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001270 }
1271
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -07001272 /**
Jack Yu643ffe42016-07-08 14:25:46 -07001273 * Update video call over LTE config
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -07001274 * @return whether feature is On
1275 * @throws ImsException
1276 */
1277 private boolean updateVideoCallFeatureValue() throws ImsException {
Brad Ebingeref267192017-08-28 13:19:22 -07001278 boolean available = isVtEnabledByPlatform();
1279 boolean enabled = isVtEnabledByUser();
1280 boolean isNonTty = isNonTtyOrTtyOnVolteEnabled();
Amit Mahajan24f7b162016-07-21 16:33:53 -07001281 boolean isDataEnabled = isDataEnabled();
Brad Ebingeref267192017-08-28 13:19:22 -07001282 boolean ignoreDataEnabledChanged = getBooleanCarrierConfig(
Jack Yu57781852016-11-16 17:20:38 -08001283 CarrierConfigManager.KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS);
Jack Yu643ffe42016-07-08 14:25:46 -07001284
Jack Yu57781852016-11-16 17:20:38 -08001285 boolean isFeatureOn = available && enabled && isNonTty
1286 && (ignoreDataEnabledChanged || isDataEnabled);
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001287
1288 log("updateVideoCallFeatureValue: available = " + available
1289 + ", enabled = " + enabled
Jack Yu643ffe42016-07-08 14:25:46 -07001290 + ", nonTTY = " + isNonTty
Amit Mahajan24f7b162016-07-21 16:33:53 -07001291 + ", data enabled = " + isDataEnabled);
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001292
1293 getConfigInterface().setFeatureValue(
1294 ImsConfig.FeatureConstants.FEATURE_TYPE_VIDEO_OVER_LTE,
1295 TelephonyManager.NETWORK_TYPE_LTE,
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -08001296 isFeatureOn ?
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001297 ImsConfig.FeatureValueConstants.ON :
1298 ImsConfig.FeatureValueConstants.OFF,
Pavel Zhamaitsiakf4b90322016-01-26 14:34:09 -08001299 mImsConfigListener);
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -07001300
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -08001301 return isFeatureOn;
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001302 }
1303
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -07001304 /**
1305 * Update WFC config
1306 * @return whether feature is On
1307 * @throws ImsException
1308 */
1309 private boolean updateWfcFeatureAndProvisionedValues() throws ImsException {
Brad Ebingeref267192017-08-28 13:19:22 -07001310 TelephonyManager tm = new TelephonyManager(mContext, getSubId());
1311 boolean isNetworkRoaming = tm.isNetworkRoaming();
1312 boolean available = isWfcEnabledByPlatform();
1313 boolean enabled = isWfcEnabledByUser();
Suresh Koleti76491082017-04-21 18:39:50 +05301314 updateDefaultWfcMode();
Brad Ebingeref267192017-08-28 13:19:22 -07001315 int mode = getWfcMode(isNetworkRoaming);
1316 boolean roaming = isWfcRoamingEnabledByUser();
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -08001317 boolean isFeatureOn = available && enabled;
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001318
1319 log("updateWfcFeatureAndProvisionedValues: available = " + available
1320 + ", enabled = " + enabled
1321 + ", mode = " + mode
1322 + ", roaming = " + roaming);
1323
1324 getConfigInterface().setFeatureValue(
Pavel Zhamaitsiake6f99432015-09-11 10:29:30 -07001325 ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_WIFI,
1326 TelephonyManager.NETWORK_TYPE_IWLAN,
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -08001327 isFeatureOn ?
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001328 ImsConfig.FeatureValueConstants.ON :
1329 ImsConfig.FeatureValueConstants.OFF,
Pavel Zhamaitsiakf4b90322016-01-26 14:34:09 -08001330 mImsConfigListener);
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001331
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -08001332 if (!isFeatureOn) {
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001333 mode = ImsConfig.WfcModeFeatureValueConstants.CELLULAR_PREFERRED;
1334 roaming = false;
1335 }
1336 setWfcModeInternal(mContext, mode);
Brad Ebinger16417b42017-03-07 13:48:50 -08001337 setWfcRoamingSettingInternal(roaming);
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -07001338
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -08001339 return isFeatureOn;
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001340 }
1341
Brad Ebinger16780ff2017-01-26 11:18:21 -08001342 /**
Brad Ebingeref267192017-08-28 13:19:22 -07001343 * Do NOT use this directly, instead use {@link #getInstance(Context, int)}.
Brad Ebinger16780ff2017-01-26 11:18:21 -08001344 */
1345 @VisibleForTesting
1346 public ImsManager(Context context, int phoneId) {
Wink Savilleef36ef62014-06-11 08:39:38 -07001347 mContext = context;
Etan Cohenabbd7882014-09-26 22:35:35 -07001348 mPhoneId = phoneId;
Brad Ebinger16780ff2017-01-26 11:18:21 -08001349 mConfigDynamicBind = mContext.getResources().getBoolean(
1350 com.android.internal.R.bool.config_dynamic_bind_ims);
Brad Ebinger16417b42017-03-07 13:48:50 -08001351 mConfigManager = (CarrierConfigManager) context.getSystemService(
1352 Context.CARRIER_CONFIG_SERVICE);
Brad Ebingerbe6cb672017-08-25 14:55:00 -07001353 if (Looper.getMainLooper() != null) {
1354 mProvisionBackoff = new ExponentialBackoff(BACKOFF_INITIAL_DELAY_MS,
1355 BACKOFF_MAX_DELAY_MS, BACKOFF_MULTIPLIER,
1356 new Handler(Looper.getMainLooper()), this::handleUpdateProvisionedValues);
1357 }
Brad Ebinger16780ff2017-01-26 11:18:21 -08001358 createImsService();
1359 }
1360
1361 /**
Brad Ebinger16780ff2017-01-26 11:18:21 -08001362 * @return Whether or not ImsManager is configured to Dynamically bind or not to support legacy
1363 * devices.
1364 */
1365 public boolean isDynamicBinding() {
1366 return mConfigDynamicBind;
Wink Savilleef36ef62014-06-11 08:39:38 -07001367 }
1368
Etan Cohenf4311122015-02-26 17:47:13 -08001369 /*
Brad Ebinger096d95c2017-06-19 15:43:08 -07001370 * Returns a flag indicating whether the IMS service is available. If it is not available,
1371 * it will try to connect before reporting failure.
Etan Cohenf4311122015-02-26 17:47:13 -08001372 */
1373 public boolean isServiceAvailable() {
Brad Ebinger096d95c2017-06-19 15:43:08 -07001374 connectIfServiceIsAvailable();
Brad Ebinger16780ff2017-01-26 11:18:21 -08001375 // mImsServiceProxy will always create an ImsServiceProxy.
1376 return mImsServiceProxy.isBinderAlive();
Etan Cohenf4311122015-02-26 17:47:13 -08001377 }
1378
Brad Ebinger096d95c2017-06-19 15:43:08 -07001379 /**
1380 * If the service is available, try to reconnect.
1381 */
1382 public void connectIfServiceIsAvailable() {
1383 if (mImsServiceProxy == null || !mImsServiceProxy.isBinderAlive()) {
1384 createImsService();
1385 }
1386 }
1387
Pavel Zhamaitsiakf4b90322016-01-26 14:34:09 -08001388 public void setImsConfigListener(ImsConfigListener listener) {
1389 mImsConfigListener = listener;
1390 }
1391
Brad Ebingerb10b61e2017-04-18 11:45:26 -07001392
1393 /**
1394 * Adds a callback for status changed events if the binder is already available. If it is not,
1395 * this method will throw an ImsException.
1396 */
1397 public void addNotifyStatusChangedCallbackIfAvailable(ImsServiceProxy.INotifyStatusChanged c)
1398 throws ImsException {
1399 if (!mImsServiceProxy.isBinderAlive()) {
1400 throw new ImsException("Binder is not active!",
1401 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1402 }
Brad Ebinger16780ff2017-01-26 11:18:21 -08001403 if (c != null) {
1404 mStatusCallbacks.add(c);
1405 }
1406 }
1407
Wink Savilleef36ef62014-06-11 08:39:38 -07001408 /**
1409 * Opens the IMS service for making calls and/or receiving generic IMS calls.
1410 * The caller may make subsquent calls through {@link #makeCall}.
1411 * The IMS service will register the device to the operator's network with the credentials
1412 * (from ISIM) periodically in order to receive calls from the operator's network.
1413 * When the IMS service receives a new call, it will send out an intent with
1414 * the provided action string.
1415 * The intent contains a call ID extra {@link getCallId} and it can be used to take a call.
1416 *
1417 * @param serviceClass a service class specified in {@link ImsServiceClass}
1418 * For VoLTE service, it MUST be a {@link ImsServiceClass#MMTEL}.
1419 * @param incomingCallPendingIntent When an incoming call is received,
1420 * the IMS service will call {@link PendingIntent#send(Context, int, Intent)} to
1421 * send back the intent to the caller with {@link #INCOMING_CALL_RESULT_CODE}
1422 * as the result code and the intent to fill in the call ID; It cannot be null
1423 * @param listener To listen to IMS registration events; It cannot be null
1424 * @return identifier (greater than 0) for the specified service
1425 * @throws NullPointerException if {@code incomingCallPendingIntent}
1426 * or {@code listener} is null
1427 * @throws ImsException if calling the IMS service results in an error
1428 * @see #getCallId
Brad Ebinger16780ff2017-01-26 11:18:21 -08001429 * @see #getImsSessionId
Wink Savilleef36ef62014-06-11 08:39:38 -07001430 */
1431 public int open(int serviceClass, PendingIntent incomingCallPendingIntent,
1432 ImsConnectionStateListener listener) throws ImsException {
1433 checkAndThrowExceptionIfServiceUnavailable();
1434
1435 if (incomingCallPendingIntent == null) {
1436 throw new NullPointerException("incomingCallPendingIntent can't be null");
1437 }
1438
1439 if (listener == null) {
1440 throw new NullPointerException("listener can't be null");
1441 }
1442
1443 int result = 0;
1444
1445 try {
Brad Ebinger445ea482017-06-13 16:21:35 -07001446 // Register a stub implementation of the ImsRegistrationListener. There is the
1447 // possibility that if we use the real implementation of the ImsRegistrationListener,
1448 // it will be added twice.
1449 // TODO: Remove ImsRegistrationListener from startSession API (b/62588776)
Brad Ebinger16780ff2017-01-26 11:18:21 -08001450 result = mImsServiceProxy.startSession(incomingCallPendingIntent,
Brad Ebinger445ea482017-06-13 16:21:35 -07001451 new ImsRegistrationListenerBase());
1452 addRegistrationListener(listener);
1453 log("open: Session started and registration listener added.");
Wink Savilleef36ef62014-06-11 08:39:38 -07001454 } catch (RemoteException e) {
1455 throw new ImsException("open()", e,
1456 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1457 }
1458
1459 if (result <= 0) {
1460 // If the return value is a minus value,
1461 // it means that an error occurred in the service.
1462 // So, it needs to convert to the reason code specified in ImsReasonInfo.
1463 throw new ImsException("open()", (result * (-1)));
1464 }
1465
1466 return result;
1467 }
1468
1469 /**
Pavel Zhamaitsiakce410172016-04-15 10:55:56 -07001470 * Adds registration listener to the IMS service.
1471 *
1472 * @param serviceClass a service class specified in {@link ImsServiceClass}
1473 * For VoLTE service, it MUST be a {@link ImsServiceClass#MMTEL}.
1474 * @param listener To listen to IMS registration events; It cannot be null
1475 * @throws NullPointerException if {@code listener} is null
1476 * @throws ImsException if calling the IMS service results in an error
Brad Ebinger64470942017-06-01 15:58:48 -07001477 *
1478 * @deprecated Use {@link #addRegistrationListener(ImsConnectionStateListener)} instead.
Pavel Zhamaitsiakce410172016-04-15 10:55:56 -07001479 */
1480 public void addRegistrationListener(int serviceClass, ImsConnectionStateListener listener)
1481 throws ImsException {
Brad Ebinger64470942017-06-01 15:58:48 -07001482 addRegistrationListener(listener);
1483 }
1484
1485 /**
1486 * Adds registration listener to the IMS service.
1487 *
1488 * @param listener To listen to IMS registration events; It cannot be null
1489 * @throws NullPointerException if {@code listener} is null
1490 * @throws ImsException if calling the IMS service results in an error
1491 */
1492 public void addRegistrationListener(ImsConnectionStateListener listener)
1493 throws ImsException {
Pavel Zhamaitsiakce410172016-04-15 10:55:56 -07001494
1495 if (listener == null) {
1496 throw new NullPointerException("listener can't be null");
1497 }
Brad Ebinger445ea482017-06-13 16:21:35 -07001498 // We only want this Proxy registered once.
Brad Ebinger64470942017-06-01 15:58:48 -07001499 synchronized (mHasRegisteredLock) {
1500 if (!mHasRegisteredForProxy) {
1501 try {
Brad Ebinger445ea482017-06-13 16:21:35 -07001502 checkAndThrowExceptionIfServiceUnavailable();
Brad Ebinger64470942017-06-01 15:58:48 -07001503 mImsServiceProxy.addRegistrationListener(mRegistrationListenerProxy);
Brad Ebinger445ea482017-06-13 16:21:35 -07001504 log("RegistrationListenerProxy registered.");
Brad Ebinger64470942017-06-01 15:58:48 -07001505 // Only record if there isn't a RemoteException.
1506 mHasRegisteredForProxy = true;
1507 } catch (RemoteException e) {
1508 throw new ImsException("addRegistrationListener()", e,
1509 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1510 }
1511 }
1512 }
1513 synchronized (mRegistrationListeners) {
Brad Ebinger445ea482017-06-13 16:21:35 -07001514 log("Local registration listener added: " + listener);
Brad Ebinger64470942017-06-01 15:58:48 -07001515 mRegistrationListeners.add(listener);
Pavel Zhamaitsiakce410172016-04-15 10:55:56 -07001516 }
1517 }
1518
1519 /**
Brad Ebinger16780ff2017-01-26 11:18:21 -08001520 * Removes the registration listener from the IMS service.
1521 *
Brad Ebinger16780ff2017-01-26 11:18:21 -08001522 * @param listener Previously registered listener that will be removed. Can not be null.
1523 * @throws NullPointerException if {@code listener} is null
1524 * @throws ImsException if calling the IMS service results in an error
1525 * instead.
1526 */
Brad Ebingerb5f30c72017-02-17 14:54:31 -08001527 public void removeRegistrationListener(ImsConnectionStateListener listener)
Brad Ebinger16780ff2017-01-26 11:18:21 -08001528 throws ImsException {
Brad Ebinger16780ff2017-01-26 11:18:21 -08001529 if (listener == null) {
1530 throw new NullPointerException("listener can't be null");
1531 }
1532
Brad Ebinger64470942017-06-01 15:58:48 -07001533 synchronized (mRegistrationListeners) {
Brad Ebinger445ea482017-06-13 16:21:35 -07001534 log("Local registration listener removed: " + listener);
Brad Ebinger64470942017-06-01 15:58:48 -07001535 mRegistrationListeners.remove(listener);
Brad Ebinger16780ff2017-01-26 11:18:21 -08001536 }
1537 }
1538
1539 /**
Wink Savilleef36ef62014-06-11 08:39:38 -07001540 * Closes the specified service ({@link ImsServiceClass}) not to make/receive calls.
1541 * All the resources that were allocated to the service are also released.
1542 *
Brad Ebinger16780ff2017-01-26 11:18:21 -08001543 * @param sessionId a session id to be closed which is obtained from {@link ImsManager#open}
Wink Savilleef36ef62014-06-11 08:39:38 -07001544 * @throws ImsException if calling the IMS service results in an error
1545 */
Brad Ebinger16780ff2017-01-26 11:18:21 -08001546 public void close(int sessionId) throws ImsException {
Wink Savilleef36ef62014-06-11 08:39:38 -07001547 checkAndThrowExceptionIfServiceUnavailable();
1548
1549 try {
Brad Ebinger16780ff2017-01-26 11:18:21 -08001550 mImsServiceProxy.endSession(sessionId);
Wink Savilleef36ef62014-06-11 08:39:38 -07001551 } catch (RemoteException e) {
1552 throw new ImsException("close()", e,
1553 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1554 } finally {
1555 mUt = null;
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -05001556 mConfig = null;
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -07001557 mEcbm = null;
Tyler Gunn4d128b62016-04-13 15:44:38 -07001558 mMultiEndpoint = null;
Wink Savilleef36ef62014-06-11 08:39:38 -07001559 }
1560 }
1561
1562 /**
1563 * Gets the configuration interface to provision / withdraw the supplementary service settings.
1564 *
Wink Savilleef36ef62014-06-11 08:39:38 -07001565 * @return the Ut interface instance
1566 * @throws ImsException if getting the Ut interface results in an error
1567 */
Brad Ebingerb5f30c72017-02-17 14:54:31 -08001568 public ImsUtInterface getSupplementaryServiceConfiguration()
Wink Savilleef36ef62014-06-11 08:39:38 -07001569 throws ImsException {
Brad Ebinger16780ff2017-01-26 11:18:21 -08001570 // FIXME: manage the multiple Ut interfaces based on the session id
Brad Ebingerf68247f2017-06-20 16:29:50 -07001571 if (mUt != null && mUt.isBinderAlive()) {
1572 return mUt;
Wink Savilleef36ef62014-06-11 08:39:38 -07001573 }
1574
Brad Ebingerf68247f2017-06-20 16:29:50 -07001575 checkAndThrowExceptionIfServiceUnavailable();
1576 try {
1577 IImsUt iUt = mImsServiceProxy.getUtInterface();
1578
1579 if (iUt == null) {
1580 throw new ImsException("getSupplementaryServiceConfiguration()",
1581 ImsReasonInfo.CODE_UT_NOT_SUPPORTED);
1582 }
1583
1584 mUt = new ImsUt(iUt);
1585 } catch (RemoteException e) {
1586 throw new ImsException("getSupplementaryServiceConfiguration()", e,
1587 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1588 }
Wink Savilleef36ef62014-06-11 08:39:38 -07001589 return mUt;
1590 }
1591
1592 /**
1593 * Checks if the IMS service has successfully registered to the IMS network
1594 * with the specified service & call type.
1595 *
Wink Savilleef36ef62014-06-11 08:39:38 -07001596 * @param serviceType a service type that is specified in {@link ImsCallProfile}
1597 * {@link ImsCallProfile#SERVICE_TYPE_NORMAL}
1598 * {@link ImsCallProfile#SERVICE_TYPE_EMERGENCY}
1599 * @param callType a call type that is specified in {@link ImsCallProfile}
1600 * {@link ImsCallProfile#CALL_TYPE_VOICE_N_VIDEO}
1601 * {@link ImsCallProfile#CALL_TYPE_VOICE}
1602 * {@link ImsCallProfile#CALL_TYPE_VT}
1603 * {@link ImsCallProfile#CALL_TYPE_VS}
1604 * @return true if the specified service id is connected to the IMS network;
1605 * false otherwise
1606 * @throws ImsException if calling the IMS service results in an error
1607 */
Brad Ebingerb5f30c72017-02-17 14:54:31 -08001608 public boolean isConnected(int serviceType, int callType)
Wink Savilleef36ef62014-06-11 08:39:38 -07001609 throws ImsException {
1610 checkAndThrowExceptionIfServiceUnavailable();
1611
1612 try {
Brad Ebingerb5f30c72017-02-17 14:54:31 -08001613 return mImsServiceProxy.isConnected(serviceType, callType);
Wink Savilleef36ef62014-06-11 08:39:38 -07001614 } catch (RemoteException e) {
1615 throw new ImsException("isServiceConnected()", e,
1616 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1617 }
1618 }
1619
1620 /**
1621 * Checks if the specified IMS service is opend.
1622 *
Wink Savilleef36ef62014-06-11 08:39:38 -07001623 * @return true if the specified service id is opened; false otherwise
1624 * @throws ImsException if calling the IMS service results in an error
1625 */
Brad Ebingerb5f30c72017-02-17 14:54:31 -08001626 public boolean isOpened() throws ImsException {
Wink Savilleef36ef62014-06-11 08:39:38 -07001627 checkAndThrowExceptionIfServiceUnavailable();
1628
1629 try {
Brad Ebingerb5f30c72017-02-17 14:54:31 -08001630 return mImsServiceProxy.isOpened();
Wink Savilleef36ef62014-06-11 08:39:38 -07001631 } catch (RemoteException e) {
1632 throw new ImsException("isOpened()", e,
1633 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1634 }
1635 }
1636
1637 /**
1638 * Creates a {@link ImsCallProfile} from the service capabilities & IMS registration state.
1639 *
Brad Ebinger16780ff2017-01-26 11:18:21 -08001640 * @param sessionId a session id which is obtained from {@link ImsManager#open}
Wink Savilleef36ef62014-06-11 08:39:38 -07001641 * @param serviceType a service type that is specified in {@link ImsCallProfile}
1642 * {@link ImsCallProfile#SERVICE_TYPE_NONE}
1643 * {@link ImsCallProfile#SERVICE_TYPE_NORMAL}
1644 * {@link ImsCallProfile#SERVICE_TYPE_EMERGENCY}
1645 * @param callType a call type that is specified in {@link ImsCallProfile}
1646 * {@link ImsCallProfile#CALL_TYPE_VOICE}
1647 * {@link ImsCallProfile#CALL_TYPE_VT}
1648 * {@link ImsCallProfile#CALL_TYPE_VT_TX}
1649 * {@link ImsCallProfile#CALL_TYPE_VT_RX}
1650 * {@link ImsCallProfile#CALL_TYPE_VT_NODIR}
1651 * {@link ImsCallProfile#CALL_TYPE_VS}
1652 * {@link ImsCallProfile#CALL_TYPE_VS_TX}
1653 * {@link ImsCallProfile#CALL_TYPE_VS_RX}
1654 * @return a {@link ImsCallProfile} object
1655 * @throws ImsException if calling the IMS service results in an error
1656 */
Brad Ebingerb5f30c72017-02-17 14:54:31 -08001657 public ImsCallProfile createCallProfile(int sessionId, int serviceType, int callType)
1658 throws ImsException {
Wink Savilleef36ef62014-06-11 08:39:38 -07001659 checkAndThrowExceptionIfServiceUnavailable();
1660
1661 try {
Brad Ebinger16780ff2017-01-26 11:18:21 -08001662 return mImsServiceProxy.createCallProfile(sessionId, serviceType, callType);
Wink Savilleef36ef62014-06-11 08:39:38 -07001663 } catch (RemoteException e) {
1664 throw new ImsException("createCallProfile()", e,
1665 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1666 }
1667 }
1668
1669 /**
1670 * Creates a {@link ImsCall} to make a call.
1671 *
Brad Ebinger16780ff2017-01-26 11:18:21 -08001672 * @param sessionId a session id which is obtained from {@link ImsManager#open}
Wink Savilleef36ef62014-06-11 08:39:38 -07001673 * @param profile a call profile to make the call
1674 * (it contains service type, call type, media information, etc.)
1675 * @param participants participants to invite the conference call
1676 * @param listener listen to the call events from {@link ImsCall}
1677 * @return a {@link ImsCall} object
1678 * @throws ImsException if calling the IMS service results in an error
1679 */
Brad Ebinger16780ff2017-01-26 11:18:21 -08001680 public ImsCall makeCall(int sessionId, ImsCallProfile profile, String[] callees,
Wink Savilleef36ef62014-06-11 08:39:38 -07001681 ImsCall.Listener listener) throws ImsException {
1682 if (DBG) {
Brad Ebinger16780ff2017-01-26 11:18:21 -08001683 log("makeCall :: sessionId=" + sessionId
fionaxu7b3107c2016-07-06 14:04:06 -07001684 + ", profile=" + profile);
Wink Savilleef36ef62014-06-11 08:39:38 -07001685 }
1686
1687 checkAndThrowExceptionIfServiceUnavailable();
1688
1689 ImsCall call = new ImsCall(mContext, profile);
1690
1691 call.setListener(listener);
Brad Ebinger16780ff2017-01-26 11:18:21 -08001692 ImsCallSession session = createCallSession(sessionId, profile);
Wink Savilleef36ef62014-06-11 08:39:38 -07001693
1694 if ((callees != null) && (callees.length == 1)) {
1695 call.start(session, callees[0]);
1696 } else {
1697 call.start(session, callees);
1698 }
1699
1700 return call;
1701 }
1702
1703 /**
1704 * Creates a {@link ImsCall} to take an incoming call.
1705 *
Brad Ebinger16780ff2017-01-26 11:18:21 -08001706 * @param sessionId a session id which is obtained from {@link ImsManager#open}
Wink Savilleef36ef62014-06-11 08:39:38 -07001707 * @param incomingCallIntent the incoming call broadcast intent
1708 * @param listener to listen to the call events from {@link ImsCall}
1709 * @return a {@link ImsCall} object
1710 * @throws ImsException if calling the IMS service results in an error
1711 */
Brad Ebinger16780ff2017-01-26 11:18:21 -08001712 public ImsCall takeCall(int sessionId, Intent incomingCallIntent,
Wink Savilleef36ef62014-06-11 08:39:38 -07001713 ImsCall.Listener listener) throws ImsException {
1714 if (DBG) {
Brad Ebinger16780ff2017-01-26 11:18:21 -08001715 log("takeCall :: sessionId=" + sessionId
Wink Savilleef36ef62014-06-11 08:39:38 -07001716 + ", incomingCall=" + incomingCallIntent);
1717 }
1718
1719 checkAndThrowExceptionIfServiceUnavailable();
1720
1721 if (incomingCallIntent == null) {
1722 throw new ImsException("Can't retrieve session with null intent",
1723 ImsReasonInfo.CODE_LOCAL_ILLEGAL_ARGUMENT);
1724 }
1725
Brad Ebinger16780ff2017-01-26 11:18:21 -08001726 int incomingServiceId = getImsSessionId(incomingCallIntent);
Wink Savilleef36ef62014-06-11 08:39:38 -07001727
Brad Ebinger16780ff2017-01-26 11:18:21 -08001728 if (sessionId != incomingServiceId) {
Wink Savilleef36ef62014-06-11 08:39:38 -07001729 throw new ImsException("Service id is mismatched in the incoming call intent",
1730 ImsReasonInfo.CODE_LOCAL_ILLEGAL_ARGUMENT);
1731 }
1732
1733 String callId = getCallId(incomingCallIntent);
1734
1735 if (callId == null) {
1736 throw new ImsException("Call ID missing in the incoming call intent",
1737 ImsReasonInfo.CODE_LOCAL_ILLEGAL_ARGUMENT);
1738 }
1739
1740 try {
Brad Ebinger16780ff2017-01-26 11:18:21 -08001741 IImsCallSession session = mImsServiceProxy.getPendingCallSession(sessionId, callId);
Wink Savilleef36ef62014-06-11 08:39:38 -07001742
1743 if (session == null) {
1744 throw new ImsException("No pending session for the call",
1745 ImsReasonInfo.CODE_LOCAL_NO_PENDING_CALL);
1746 }
1747
1748 ImsCall call = new ImsCall(mContext, session.getCallProfile());
1749
1750 call.attachSession(new ImsCallSession(session));
1751 call.setListener(listener);
1752
1753 return call;
1754 } catch (Throwable t) {
1755 throw new ImsException("takeCall()", t, ImsReasonInfo.CODE_UNSPECIFIED);
1756 }
1757 }
1758
1759 /**
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -05001760 * Gets the config interface to get/set service/capability parameters.
1761 *
1762 * @return the ImsConfig instance.
1763 * @throws ImsException if getting the setting interface results in an error.
1764 */
1765 public ImsConfig getConfigInterface() throws ImsException {
Brad Ebingerf68247f2017-06-20 16:29:50 -07001766 if (mConfig != null && mConfig.isBinderAlive()) {
1767 return mConfig;
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -05001768 }
Brad Ebingerf68247f2017-06-20 16:29:50 -07001769
1770 checkAndThrowExceptionIfServiceUnavailable();
1771 try {
1772 IImsConfig config = mImsServiceProxy.getConfigInterface();
1773 if (config == null) {
1774 throw new ImsException("getConfigInterface()",
1775 ImsReasonInfo.CODE_LOCAL_SERVICE_UNAVAILABLE);
1776 }
1777 mConfig = new ImsConfig(config, mContext);
1778 } catch (RemoteException e) {
1779 throw new ImsException("getConfigInterface()", e,
1780 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1781 }
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -05001782 return mConfig;
1783 }
1784
Hall Liue511a202017-08-17 15:49:58 -07001785 /**
1786 * Set the TTY mode. This is the actual tty mode (varies depending on peripheral status)
1787 */
1788 public void setTtyMode(int ttyMode) throws ImsException {
Brad Ebingeref267192017-08-28 13:19:22 -07001789 if (!getBooleanCarrierConfig(
Hall Liue511a202017-08-17 15:49:58 -07001790 CarrierConfigManager.KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL)) {
1791 setAdvanced4GMode((ttyMode == TelecomManager.TTY_MODE_OFF) &&
Brad Ebingeref267192017-08-28 13:19:22 -07001792 isEnhanced4gLteModeSettingEnabledByUser());
Hall Liue511a202017-08-17 15:49:58 -07001793 }
1794 }
1795
1796 /**
1797 * Sets the UI TTY mode. This is the preferred TTY mode that the user sets in the call
1798 * settings screen.
1799 */
Brad Ebingerb5f30c72017-02-17 14:54:31 -08001800 public void setUiTTYMode(Context context, int uiTtyMode, Message onComplete)
Shriram Ganeshc403b7b2014-08-14 14:18:57 +05301801 throws ImsException {
1802
Etan Cohen82f78122014-12-15 10:10:14 -08001803 checkAndThrowExceptionIfServiceUnavailable();
Shriram Ganeshc403b7b2014-08-14 14:18:57 +05301804
Etan Cohen82f78122014-12-15 10:10:14 -08001805 try {
Brad Ebingerb5f30c72017-02-17 14:54:31 -08001806 mImsServiceProxy.setUiTTYMode(uiTtyMode, onComplete);
Etan Cohen82f78122014-12-15 10:10:14 -08001807 } catch (RemoteException e) {
1808 throw new ImsException("setTTYMode()", e,
1809 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1810 }
Shriram Ganeshc403b7b2014-08-14 14:18:57 +05301811 }
1812
Naveen Kalla525c3a22017-02-06 14:46:42 -08001813 private ImsReasonInfo makeACopy(ImsReasonInfo imsReasonInfo) {
1814 Parcel p = Parcel.obtain();
1815 imsReasonInfo.writeToParcel(p, 0);
1816 p.setDataPosition(0);
1817 ImsReasonInfo clonedReasonInfo = ImsReasonInfo.CREATOR.createFromParcel(p);
1818 p.recycle();
1819 return clonedReasonInfo;
1820 }
1821
1822 /**
1823 * Get Recent IMS Disconnect Reasons.
1824 *
1825 * @return ArrayList of ImsReasonInfo objects. MAX size of the arraylist
1826 * is MAX_RECENT_DISCONNECT_REASONS. The objects are in the
1827 * chronological order.
1828 */
1829 public ArrayList<ImsReasonInfo> getRecentImsDisconnectReasons() {
1830 ArrayList<ImsReasonInfo> disconnectReasons = new ArrayList<>();
1831
1832 for (ImsReasonInfo reason : mRecentDisconnectReasons) {
1833 disconnectReasons.add(makeACopy(reason));
1834 }
1835 return disconnectReasons;
1836 }
Brad Ebinger16417b42017-03-07 13:48:50 -08001837
Brad Ebinger16780ff2017-01-26 11:18:21 -08001838 public int getImsServiceStatus() throws ImsException {
Brad Ebinger16780ff2017-01-26 11:18:21 -08001839 return mImsServiceProxy.getFeatureStatus();
1840 }
Naveen Kalla525c3a22017-02-06 14:46:42 -08001841
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -05001842 /**
Junda Liue7663c02015-06-23 11:16:26 -07001843 * Get the boolean config from carrier config manager.
1844 *
Brad Ebinger16417b42017-03-07 13:48:50 -08001845 * @param key config key defined in CarrierConfigManager
1846 * @return boolean value of corresponding key.
1847 */
Brad Ebingeref267192017-08-28 13:19:22 -07001848 private boolean getBooleanCarrierConfig(String key) {
Brad Ebinger16417b42017-03-07 13:48:50 -08001849 int[] subIds = SubscriptionManager.getSubId(mPhoneId);
1850 int subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1851 if (subIds != null && subIds.length >= 1) {
1852 subId = subIds[0];
1853 }
1854 PersistableBundle b = null;
1855 if (mConfigManager != null) {
1856 // If an invalid subId is used, this bundle will contain default values.
1857 b = mConfigManager.getConfigForSubId(subId);
1858 }
1859 if (b != null) {
1860 return b.getBoolean(key);
1861 } else {
1862 // Return static default defined in CarrierConfigManager.
1863 return CarrierConfigManager.getDefaultConfig().getBoolean(key);
1864 }
1865 }
1866
1867 /**
fionaxu5803ef02016-03-08 11:48:48 -08001868 * Get the int config from carrier config manager.
1869 *
Brad Ebinger16417b42017-03-07 13:48:50 -08001870 * @param key config key defined in CarrierConfigManager
1871 * @return integer value of corresponding key.
1872 */
Brad Ebingeref267192017-08-28 13:19:22 -07001873 private int getIntCarrierConfig(String key) {
Brad Ebinger16417b42017-03-07 13:48:50 -08001874 int[] subIds = SubscriptionManager.getSubId(mPhoneId);
1875 int subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1876 if (subIds != null && subIds.length >= 1) {
1877 subId = subIds[0];
1878 }
1879 PersistableBundle b = null;
1880 if (mConfigManager != null) {
1881 // If an invalid subId is used, this bundle will contain default values.
1882 b = mConfigManager.getConfigForSubId(subId);
1883 }
1884 if (b != null) {
1885 return b.getInt(key);
1886 } else {
1887 // Return static default defined in CarrierConfigManager.
1888 return CarrierConfigManager.getDefaultConfig().getInt(key);
1889 }
1890 }
1891
1892 /**
Wink Savilleef36ef62014-06-11 08:39:38 -07001893 * Gets the call ID from the specified incoming call broadcast intent.
1894 *
1895 * @param incomingCallIntent the incoming call broadcast intent
1896 * @return the call ID or null if the intent does not contain it
1897 */
1898 private static String getCallId(Intent incomingCallIntent) {
1899 if (incomingCallIntent == null) {
1900 return null;
1901 }
1902
1903 return incomingCallIntent.getStringExtra(EXTRA_CALL_ID);
1904 }
1905
1906 /**
1907 * Gets the service type from the specified incoming call broadcast intent.
1908 *
1909 * @param incomingCallIntent the incoming call broadcast intent
Brad Ebinger16780ff2017-01-26 11:18:21 -08001910 * @return the session identifier or -1 if the intent does not contain it
Wink Savilleef36ef62014-06-11 08:39:38 -07001911 */
Brad Ebinger16780ff2017-01-26 11:18:21 -08001912 private static int getImsSessionId(Intent incomingCallIntent) {
Wink Savilleef36ef62014-06-11 08:39:38 -07001913 if (incomingCallIntent == null) {
1914 return (-1);
1915 }
1916
1917 return incomingCallIntent.getIntExtra(EXTRA_SERVICE_ID, -1);
1918 }
1919
1920 /**
Brad Ebingerb10b61e2017-04-18 11:45:26 -07001921 * Checks to see if the ImsService Binder is connected. If it is not, we try to create the
1922 * connection again.
Wink Savilleef36ef62014-06-11 08:39:38 -07001923 */
1924 private void checkAndThrowExceptionIfServiceUnavailable()
1925 throws ImsException {
Brad Ebinger16780ff2017-01-26 11:18:21 -08001926 if (mImsServiceProxy == null || !mImsServiceProxy.isBinderAlive()) {
1927 createImsService();
Wink Savilleef36ef62014-06-11 08:39:38 -07001928
Brad Ebinger16780ff2017-01-26 11:18:21 -08001929 if (mImsServiceProxy == null) {
Wink Savilleef36ef62014-06-11 08:39:38 -07001930 throw new ImsException("Service is unavailable",
1931 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1932 }
1933 }
1934 }
1935
Brad Ebinger16780ff2017-01-26 11:18:21 -08001936 /**
1937 * Binds the IMS service to make/receive the call. Supports two methods of exposing an
1938 * ImsService:
1939 * 1) com.android.ims.ImsService implementation in ServiceManager (deprecated).
1940 * 2) android.telephony.ims.ImsService implementation through ImsResolver.
1941 */
1942 private void createImsService() {
1943 if (!mConfigDynamicBind) {
1944 // Old method of binding
1945 Rlog.i(TAG, "Creating ImsService using ServiceManager");
1946 mImsServiceProxy = getServiceProxyCompat();
1947 } else {
1948 Rlog.i(TAG, "Creating ImsService using ImsResolver");
1949 mImsServiceProxy = getServiceProxy();
1950 }
Brad Ebinger64470942017-06-01 15:58:48 -07001951 // We have created a new ImsService connection, signal for re-registration
1952 synchronized (mHasRegisteredLock) {
1953 mHasRegisteredForProxy = false;
1954 }
Etan Cohend7727462014-07-12 14:54:10 -07001955 }
1956
Brad Ebinger16780ff2017-01-26 11:18:21 -08001957 // Deprecated method of binding with the ImsService defined in the ServiceManager.
1958 private ImsServiceProxyCompat getServiceProxyCompat() {
1959 IBinder binder = ServiceManager.checkService(IMS_SERVICE);
Wink Savilleef36ef62014-06-11 08:39:38 -07001960
Brad Ebinger16780ff2017-01-26 11:18:21 -08001961 if (binder != null) {
Wink Savilleef36ef62014-06-11 08:39:38 -07001962 try {
Brad Ebinger16780ff2017-01-26 11:18:21 -08001963 binder.linkToDeath(mDeathRecipient, 0);
Wink Savilleef36ef62014-06-11 08:39:38 -07001964 } catch (RemoteException e) {
1965 }
1966 }
1967
Brad Ebinger16780ff2017-01-26 11:18:21 -08001968 return new ImsServiceProxyCompat(mPhoneId, binder);
1969 }
1970
1971 // New method of binding with the ImsResolver
1972 private ImsServiceProxy getServiceProxy() {
1973 TelephonyManager tm = (TelephonyManager)
1974 mContext.getSystemService(Context.TELEPHONY_SERVICE);
1975 ImsServiceProxy serviceProxy = new ImsServiceProxy(mPhoneId, ImsFeature.MMTEL);
Brad Ebingerb10b61e2017-04-18 11:45:26 -07001976 serviceProxy.setStatusCallback(() -> mStatusCallbacks.forEach(
1977 ImsServiceProxy.INotifyStatusChanged::notifyStatusChanged));
Brad Ebinger16780ff2017-01-26 11:18:21 -08001978 // Returns null if the service is not available.
1979 IImsServiceController b = tm.getImsServiceControllerAndListen(mPhoneId,
1980 ImsFeature.MMTEL, serviceProxy.getListener());
1981 if (b != null) {
1982 serviceProxy.setBinder(b.asBinder());
Brad Ebinger16780ff2017-01-26 11:18:21 -08001983 // Trigger the cache to be updated for feature status.
1984 serviceProxy.getFeatureStatus();
Brad Ebinger16780ff2017-01-26 11:18:21 -08001985 } else {
1986 Rlog.w(TAG, "getServiceProxy: b is null! Phone Id: " + mPhoneId);
1987 }
1988 return serviceProxy;
Wink Savilleef36ef62014-06-11 08:39:38 -07001989 }
1990
1991 /**
1992 * Creates a {@link ImsCallSession} with the specified call profile.
1993 * Use other methods, if applicable, instead of interacting with
1994 * {@link ImsCallSession} directly.
1995 *
1996 * @param serviceId a service id which is obtained from {@link ImsManager#open}
1997 * @param profile a call profile to make the call
1998 */
1999 private ImsCallSession createCallSession(int serviceId,
2000 ImsCallProfile profile) throws ImsException {
2001 try {
Brad Ebingerb10b61e2017-04-18 11:45:26 -07002002 // Throws an exception if the ImsService Feature is not ready to accept commands.
Brad Ebinger16780ff2017-01-26 11:18:21 -08002003 return new ImsCallSession(mImsServiceProxy.createCallSession(serviceId, profile, null));
Wink Savilleef36ef62014-06-11 08:39:38 -07002004 } catch (RemoteException e) {
Brad Ebingerb10b61e2017-04-18 11:45:26 -07002005 Rlog.w(TAG, "CreateCallSession: Error, remote exception: " + e.getMessage());
2006 throw new ImsException("createCallSession()", e,
2007 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
2008
Wink Savilleef36ef62014-06-11 08:39:38 -07002009 }
2010 }
2011
Etan Cohena00c9192014-12-23 15:02:29 -08002012 private static void log(String s) {
Wink Savilleef36ef62014-06-11 08:39:38 -07002013 Rlog.d(TAG, s);
2014 }
2015
Etan Cohena00c9192014-12-23 15:02:29 -08002016 private static void loge(String s) {
Wink Savilleef36ef62014-06-11 08:39:38 -07002017 Rlog.e(TAG, s);
2018 }
2019
Etan Cohena00c9192014-12-23 15:02:29 -08002020 private static void loge(String s, Throwable t) {
Wink Savilleef36ef62014-06-11 08:39:38 -07002021 Rlog.e(TAG, s, t);
2022 }
2023
2024 /**
ram7da5a112014-07-16 20:59:27 +05302025 * Used for turning on IMS.if its off already
2026 */
Etan Cohen82f78122014-12-15 10:10:14 -08002027 private void turnOnIms() throws ImsException {
Etan Cohen0c9c09e2014-07-25 11:09:12 -07002028 checkAndThrowExceptionIfServiceUnavailable();
2029
ram7da5a112014-07-16 20:59:27 +05302030 try {
Brad Ebingerb5f30c72017-02-17 14:54:31 -08002031 mImsServiceProxy.turnOnIms();
ram7da5a112014-07-16 20:59:27 +05302032 } catch (RemoteException e) {
2033 throw new ImsException("turnOnIms() ", e, ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
2034 }
2035 }
2036
Omkar Kolangade75f3ca32014-10-24 11:10:52 -07002037 private boolean isImsTurnOffAllowed() {
Brad Ebingeref267192017-08-28 13:19:22 -07002038 return isTurnOffImsAllowedByPlatform()
2039 && (!isWfcEnabledByPlatform()
2040 || !isWfcEnabledByUser());
Omkar Kolangade75f3ca32014-10-24 11:10:52 -07002041 }
2042
Amit Mahajan9cba36d2016-08-11 10:17:23 -07002043 private void setLteFeatureValues(boolean turnOn) {
2044 log("setLteFeatureValues: " + turnOn);
Omkar Kolangade75f3ca32014-10-24 11:10:52 -07002045 try {
2046 ImsConfig config = getConfigInterface();
Amit Mahajan9cba36d2016-08-11 10:17:23 -07002047 if (config != null) {
Omkar Kolangade75f3ca32014-10-24 11:10:52 -07002048 config.setFeatureValue(ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_LTE,
Pavel Zhamaitsiakf4b90322016-01-26 14:34:09 -08002049 TelephonyManager.NETWORK_TYPE_LTE, turnOn ? 1 : 0, mImsConfigListener);
Pavel Zhamaitsiakff29b9d2016-04-15 12:16:57 -07002050
Brad Ebingeref267192017-08-28 13:19:22 -07002051 if (isVolteEnabledByPlatform()) {
2052 boolean ignoreDataEnabledChanged = getBooleanCarrierConfig(
Jack Yu57781852016-11-16 17:20:38 -08002053 CarrierConfigManager.KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS);
Brad Ebingeref267192017-08-28 13:19:22 -07002054 boolean enableViLte = turnOn && isVtEnabledByUser() &&
Jack Yu57781852016-11-16 17:20:38 -08002055 (ignoreDataEnabledChanged || isDataEnabled());
Pavel Zhamaitsiakff29b9d2016-04-15 12:16:57 -07002056 config.setFeatureValue(ImsConfig.FeatureConstants.FEATURE_TYPE_VIDEO_OVER_LTE,
2057 TelephonyManager.NETWORK_TYPE_LTE,
2058 enableViLte ? 1 : 0,
2059 mImsConfigListener);
2060 }
Etan Cohenb651fa52014-10-22 10:51:29 -07002061 }
Omkar Kolangade75f3ca32014-10-24 11:10:52 -07002062 } catch (ImsException e) {
Amit Mahajan9cba36d2016-08-11 10:17:23 -07002063 loge("setLteFeatureValues: exception ", e);
Etan Cohencfc784d2014-08-07 18:40:31 -07002064 }
Amit Mahajan9cba36d2016-08-11 10:17:23 -07002065 }
2066
2067 private void setAdvanced4GMode(boolean turnOn) throws ImsException {
2068 checkAndThrowExceptionIfServiceUnavailable();
2069
2070 // if turnOn: first set feature values then call turnOnIms()
2071 // if turnOff: only set feature values if IMS turn off is not allowed. If turn off is
2072 // allowed, first call turnOffIms() then set feature values
Etan Cohencfc784d2014-08-07 18:40:31 -07002073 if (turnOn) {
Amit Mahajan9cba36d2016-08-11 10:17:23 -07002074 setLteFeatureValues(turnOn);
2075 log("setAdvanced4GMode: turnOnIms");
Etan Cohencfc784d2014-08-07 18:40:31 -07002076 turnOnIms();
Amit Mahajan9cba36d2016-08-11 10:17:23 -07002077 } else {
2078 if (isImsTurnOffAllowed()) {
2079 log("setAdvanced4GMode: turnOffIms");
2080 turnOffIms();
2081 }
2082 setLteFeatureValues(turnOn);
Etan Cohencfc784d2014-08-07 18:40:31 -07002083 }
2084 }
2085
ram7da5a112014-07-16 20:59:27 +05302086 /**
2087 * Used for turning off IMS completely in order to make the device CSFB'ed.
2088 * Once turned off, all calls will be over CS.
2089 */
Etan Cohen82f78122014-12-15 10:10:14 -08002090 private void turnOffIms() throws ImsException {
Etan Cohen0c9c09e2014-07-25 11:09:12 -07002091 checkAndThrowExceptionIfServiceUnavailable();
2092
ram7da5a112014-07-16 20:59:27 +05302093 try {
Brad Ebingerb5f30c72017-02-17 14:54:31 -08002094 mImsServiceProxy.turnOffIms();
ram7da5a112014-07-16 20:59:27 +05302095 } catch (RemoteException e) {
2096 throw new ImsException("turnOffIms() ", e, ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
2097 }
2098 }
2099
Naveen Kalla525c3a22017-02-06 14:46:42 -08002100 private void addToRecentDisconnectReasons(ImsReasonInfo reason) {
2101 if (reason == null) return;
2102 while (mRecentDisconnectReasons.size() >= MAX_RECENT_DISCONNECT_REASONS) {
2103 mRecentDisconnectReasons.removeFirst();
2104 }
2105 mRecentDisconnectReasons.addLast(reason);
2106 }
2107
ram7da5a112014-07-16 20:59:27 +05302108 /**
Wink Savilleef36ef62014-06-11 08:39:38 -07002109 * Death recipient class for monitoring IMS service.
2110 */
2111 private class ImsServiceDeathRecipient implements IBinder.DeathRecipient {
2112 @Override
2113 public void binderDied() {
Brad Ebinger16780ff2017-01-26 11:18:21 -08002114 mImsServiceProxy = null;
Wink Savilleef36ef62014-06-11 08:39:38 -07002115 mUt = null;
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -05002116 mConfig = null;
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -07002117 mEcbm = null;
Tyler Gunn4d128b62016-04-13 15:44:38 -07002118 mMultiEndpoint = null;
Wink Savilleef36ef62014-06-11 08:39:38 -07002119 }
2120 }
2121
2122 /**
Brad Ebinger445ea482017-06-13 16:21:35 -07002123 * Stub implementation of the Registration listener that provides no functionality.
2124 */
2125 private class ImsRegistrationListenerBase extends IImsRegistrationListener.Stub {
2126
2127 @Override
2128 public void registrationConnected() throws RemoteException {
2129 }
2130
2131 @Override
2132 public void registrationProgressing() throws RemoteException {
2133 }
2134
2135 @Override
2136 public void registrationConnectedWithRadioTech(int imsRadioTech) throws RemoteException {
2137 }
2138
2139 @Override
2140 public void registrationProgressingWithRadioTech(int imsRadioTech) throws RemoteException {
2141 }
2142
2143 @Override
2144 public void registrationDisconnected(ImsReasonInfo imsReasonInfo) throws RemoteException {
2145 }
2146
2147 @Override
2148 public void registrationResumed() throws RemoteException {
2149 }
2150
2151 @Override
2152 public void registrationSuspended() throws RemoteException {
2153 }
2154
2155 @Override
2156 public void registrationServiceCapabilityChanged(int serviceClass, int event)
2157 throws RemoteException {
2158 }
2159
2160 @Override
2161 public void registrationFeatureCapabilityChanged(int serviceClass, int[] enabledFeatures,
2162 int[] disabledFeatures) throws RemoteException {
2163 }
2164
2165 @Override
2166 public void voiceMessageCountUpdate(int count) throws RemoteException {
2167 }
2168
2169 @Override
2170 public void registrationAssociatedUriChanged(Uri[] uris) throws RemoteException {
2171 }
2172
2173 @Override
2174 public void registrationChangeFailed(int targetAccessTech, ImsReasonInfo imsReasonInfo)
2175 throws RemoteException {
2176 }
2177 }
2178
2179 /**
Wink Savilleef36ef62014-06-11 08:39:38 -07002180 * Adapter class for {@link IImsRegistrationListener}.
2181 */
Naveen Kalla196fd3b2017-02-14 14:55:24 -08002182 private class ImsRegistrationListenerProxy extends IImsRegistrationListener.Stub {
Wink Savilleef36ef62014-06-11 08:39:38 -07002183
Omkar Kolangadea7ced642015-05-04 17:55:13 -07002184 @Deprecated
Wink Savilleef36ef62014-06-11 08:39:38 -07002185 public void registrationConnected() {
2186 if (DBG) {
2187 log("registrationConnected ::");
2188 }
2189
Brad Ebinger64470942017-06-01 15:58:48 -07002190 synchronized (mRegistrationListeners) {
2191 mRegistrationListeners.forEach(l -> l.onImsConnected(
2192 ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN));
Wink Savilleef36ef62014-06-11 08:39:38 -07002193 }
2194 }
2195
Omkar Kolangadea7ced642015-05-04 17:55:13 -07002196 @Deprecated
Rekha Kumar14631742015-02-04 10:47:00 -08002197 public void registrationProgressing() {
Wink Savilleef36ef62014-06-11 08:39:38 -07002198 if (DBG) {
Rekha Kumar14631742015-02-04 10:47:00 -08002199 log("registrationProgressing ::");
Wink Savilleef36ef62014-06-11 08:39:38 -07002200 }
2201
Brad Ebinger64470942017-06-01 15:58:48 -07002202 synchronized (mRegistrationListeners) {
2203 mRegistrationListeners.forEach(l -> l.onImsProgressing(
2204 ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN));
Rekha Kumar14631742015-02-04 10:47:00 -08002205 }
2206 }
2207
2208 @Override
Omkar Kolangadea7ced642015-05-04 17:55:13 -07002209 public void registrationConnectedWithRadioTech(int imsRadioTech) {
2210 // Note: imsRadioTech value maps to RIL_RADIO_TECHNOLOGY
2211 // values in ServiceState.java.
2212 if (DBG) {
2213 log("registrationConnectedWithRadioTech :: imsRadioTech=" + imsRadioTech);
2214 }
2215
Brad Ebinger64470942017-06-01 15:58:48 -07002216 synchronized (mRegistrationListeners) {
2217 mRegistrationListeners.forEach(l -> l.onImsConnected(imsRadioTech));
Omkar Kolangadea7ced642015-05-04 17:55:13 -07002218 }
2219 }
2220
2221 @Override
2222 public void registrationProgressingWithRadioTech(int imsRadioTech) {
2223 // Note: imsRadioTech value maps to RIL_RADIO_TECHNOLOGY
2224 // values in ServiceState.java.
2225 if (DBG) {
2226 log("registrationProgressingWithRadioTech :: imsRadioTech=" + imsRadioTech);
2227 }
2228
Brad Ebinger64470942017-06-01 15:58:48 -07002229 synchronized (mRegistrationListeners) {
2230 mRegistrationListeners.forEach(l -> l.onImsProgressing(imsRadioTech));
Omkar Kolangadea7ced642015-05-04 17:55:13 -07002231 }
2232 }
2233
2234 @Override
Rekha Kumar14631742015-02-04 10:47:00 -08002235 public void registrationDisconnected(ImsReasonInfo imsReasonInfo) {
2236 if (DBG) {
2237 log("registrationDisconnected :: imsReasonInfo" + imsReasonInfo);
2238 }
2239
Naveen Kalla525c3a22017-02-06 14:46:42 -08002240 addToRecentDisconnectReasons(imsReasonInfo);
Brad Ebinger64470942017-06-01 15:58:48 -07002241 synchronized (mRegistrationListeners) {
2242 mRegistrationListeners.forEach(l -> l.onImsDisconnected(imsReasonInfo));
Wink Savilleef36ef62014-06-11 08:39:38 -07002243 }
2244 }
2245
2246 @Override
2247 public void registrationResumed() {
2248 if (DBG) {
2249 log("registrationResumed ::");
2250 }
2251
Brad Ebinger64470942017-06-01 15:58:48 -07002252 synchronized (mRegistrationListeners) {
2253 mRegistrationListeners.forEach(ImsConnectionStateListener::onImsResumed);
Wink Savilleef36ef62014-06-11 08:39:38 -07002254 }
2255 }
2256
2257 @Override
2258 public void registrationSuspended() {
2259 if (DBG) {
2260 log("registrationSuspended ::");
2261 }
2262
Brad Ebinger64470942017-06-01 15:58:48 -07002263 synchronized (mRegistrationListeners) {
2264 mRegistrationListeners.forEach(ImsConnectionStateListener::onImsSuspended);
Wink Savilleef36ef62014-06-11 08:39:38 -07002265 }
2266 }
2267
2268 @Override
2269 public void registrationServiceCapabilityChanged(int serviceClass, int event) {
2270 log("registrationServiceCapabilityChanged :: serviceClass=" +
2271 serviceClass + ", event=" + event);
2272
Brad Ebinger64470942017-06-01 15:58:48 -07002273 synchronized (mRegistrationListeners) {
2274 mRegistrationListeners.forEach(l -> l.onImsConnected(
2275 ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN));
Wink Savilleef36ef62014-06-11 08:39:38 -07002276 }
2277 }
ram7da5a112014-07-16 20:59:27 +05302278
2279 @Override
2280 public void registrationFeatureCapabilityChanged(int serviceClass,
2281 int[] enabledFeatures, int[] disabledFeatures) {
2282 log("registrationFeatureCapabilityChanged :: serviceClass=" +
2283 serviceClass);
Brad Ebinger64470942017-06-01 15:58:48 -07002284
2285 synchronized (mRegistrationListeners) {
2286 mRegistrationListeners.forEach(l -> l.onFeatureCapabilityChanged(serviceClass,
2287 enabledFeatures, disabledFeatures));
Libin.Tang@motorola.come2296782014-08-19 14:20:01 -05002288 }
ram7da5a112014-07-16 20:59:27 +05302289 }
2290
Shriram Ganeshd3adfad2015-05-31 10:06:15 -07002291 @Override
2292 public void voiceMessageCountUpdate(int count) {
2293 log("voiceMessageCountUpdate :: count=" + count);
2294
Brad Ebinger64470942017-06-01 15:58:48 -07002295 synchronized (mRegistrationListeners) {
2296 mRegistrationListeners.forEach(l -> l.onVoiceMessageCountChanged(count));
Shriram Ganeshd3adfad2015-05-31 10:06:15 -07002297 }
2298 }
2299
Pavel Zhamaitsiak4de9cbb2016-02-11 17:21:05 -08002300 @Override
2301 public void registrationAssociatedUriChanged(Uri[] uris) {
2302 if (DBG) log("registrationAssociatedUriChanged ::");
2303
Brad Ebinger64470942017-06-01 15:58:48 -07002304 synchronized (mRegistrationListeners) {
2305 mRegistrationListeners.forEach(l -> l.registrationAssociatedUriChanged(uris));
Pavel Zhamaitsiak4de9cbb2016-02-11 17:21:05 -08002306 }
2307 }
Meng Wangbb98b9b2016-12-07 16:27:15 -08002308
2309 @Override
2310 public void registrationChangeFailed(int targetAccessTech, ImsReasonInfo imsReasonInfo) {
2311 if (DBG) log("registrationChangeFailed :: targetAccessTech=" + targetAccessTech +
2312 ", imsReasonInfo=" + imsReasonInfo);
2313
Brad Ebinger64470942017-06-01 15:58:48 -07002314 synchronized (mRegistrationListeners) {
2315 mRegistrationListeners.forEach(l -> l.onRegistrationChangeFailed(targetAccessTech,
2316 imsReasonInfo));
Meng Wangbb98b9b2016-12-07 16:27:15 -08002317 }
2318 }
Wink Savilleef36ef62014-06-11 08:39:38 -07002319 }
Tyler Gunn4d128b62016-04-13 15:44:38 -07002320
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -07002321 /**
2322 * Gets the ECBM interface to request ECBM exit.
2323 *
2324 * @param serviceId a service id which is obtained from {@link ImsManager#open}
2325 * @return the ECBM interface instance
2326 * @throws ImsException if getting the ECBM interface results in an error
2327 */
2328 public ImsEcbm getEcbmInterface(int serviceId) throws ImsException {
Brad Ebingerf68247f2017-06-20 16:29:50 -07002329 if (mEcbm != null && mEcbm.isBinderAlive()) {
2330 return mEcbm;
2331 }
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -07002332
Brad Ebingerf68247f2017-06-20 16:29:50 -07002333 checkAndThrowExceptionIfServiceUnavailable();
2334 try {
2335 IImsEcbm iEcbm = mImsServiceProxy.getEcbmInterface();
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -07002336
Brad Ebingerf68247f2017-06-20 16:29:50 -07002337 if (iEcbm == null) {
2338 throw new ImsException("getEcbmInterface()",
2339 ImsReasonInfo.CODE_ECBM_NOT_SUPPORTED);
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -07002340 }
Brad Ebingerf68247f2017-06-20 16:29:50 -07002341 mEcbm = new ImsEcbm(iEcbm);
2342 } catch (RemoteException e) {
2343 throw new ImsException("getEcbmInterface()", e,
2344 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -07002345 }
2346 return mEcbm;
2347 }
Pavel Zhamaitsiak8c065f52015-11-10 14:36:44 -08002348
2349 /**
Tyler Gunn4d128b62016-04-13 15:44:38 -07002350 * Gets the Multi-Endpoint interface to subscribe to multi-enpoint notifications..
2351 *
2352 * @param serviceId a service id which is obtained from {@link ImsManager#open}
2353 * @return the multi-endpoint interface instance
2354 * @throws ImsException if getting the multi-endpoint interface results in an error
2355 */
2356 public ImsMultiEndpoint getMultiEndpointInterface(int serviceId) throws ImsException {
Brad Ebingerf68247f2017-06-20 16:29:50 -07002357 if (mMultiEndpoint != null && mMultiEndpoint.isBinderAlive()) {
2358 return mMultiEndpoint;
Tyler Gunn4d128b62016-04-13 15:44:38 -07002359 }
Brad Ebingerf68247f2017-06-20 16:29:50 -07002360
2361 checkAndThrowExceptionIfServiceUnavailable();
2362 try {
2363 IImsMultiEndpoint iImsMultiEndpoint = mImsServiceProxy.getMultiEndpointInterface();
2364
2365 if (iImsMultiEndpoint == null) {
2366 throw new ImsException("getMultiEndpointInterface()",
2367 ImsReasonInfo.CODE_MULTIENDPOINT_NOT_SUPPORTED);
2368 }
2369 mMultiEndpoint = new ImsMultiEndpoint(iImsMultiEndpoint);
2370 } catch (RemoteException e) {
2371 throw new ImsException("getMultiEndpointInterface()", e,
2372 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
2373 }
2374
Tyler Gunn4d128b62016-04-13 15:44:38 -07002375 return mMultiEndpoint;
2376 }
2377
2378 /**
Pavel Zhamaitsiak8c065f52015-11-10 14:36:44 -08002379 * Resets ImsManager settings back to factory defaults.
2380 *
Brad Ebingeref267192017-08-28 13:19:22 -07002381 * @deprecated Doesn't support MSIM devices. Use {@link #factoryReset()} instead.
Brad Ebinger16417b42017-03-07 13:48:50 -08002382 *
Pavel Zhamaitsiak8c065f52015-11-10 14:36:44 -08002383 * @hide
2384 */
2385 public static void factoryReset(Context context) {
Brad Ebingeref267192017-08-28 13:19:22 -07002386 ImsManager mgr = ImsManager.getInstance(context,
2387 SubscriptionManager.getDefaultVoicePhoneId());
2388 if (mgr != null) {
2389 mgr.factoryReset();
2390 }
2391 loge("factoryReset: ImsManager null.");
Pavel Zhamaitsiak8c065f52015-11-10 14:36:44 -08002392 }
Jack Yu2f102bd2015-12-28 15:31:48 -08002393
Brad Ebinger16417b42017-03-07 13:48:50 -08002394 /**
2395 * Resets ImsManager settings back to factory defaults.
2396 *
2397 * @hide
2398 */
Brad Ebingeref267192017-08-28 13:19:22 -07002399 public void factoryReset() {
Brad Ebinger16417b42017-03-07 13:48:50 -08002400 // Set VoLTE to default
Malcolm Chen212ca652017-09-28 17:28:45 -07002401 SubscriptionManager.setSubscriptionProperty(getSubId(),
2402 SubscriptionManager.ENHANCED_4G_MODE_ENABLED, booleanToPropertyString(true));
Brad Ebinger16417b42017-03-07 13:48:50 -08002403
2404 // Set VoWiFi to default
Malcolm Chen212ca652017-09-28 17:28:45 -07002405 SubscriptionManager.setSubscriptionProperty(getSubId(),
2406 SubscriptionManager.WFC_IMS_ENABLED,
2407 booleanToPropertyString(getBooleanCarrierConfig(
2408 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ENABLED_BOOL)));
Brad Ebinger16417b42017-03-07 13:48:50 -08002409
2410 // Set VoWiFi mode to default
Malcolm Chen212ca652017-09-28 17:28:45 -07002411 SubscriptionManager.setSubscriptionProperty(getSubId(),
2412 SubscriptionManager.WFC_IMS_MODE,
2413 Integer.toString(getIntCarrierConfig(
2414 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_MODE_INT)));
Brad Ebinger16417b42017-03-07 13:48:50 -08002415
2416 // Set VoWiFi roaming to default
Malcolm Chen212ca652017-09-28 17:28:45 -07002417 SubscriptionManager.setSubscriptionProperty(getSubId(),
2418 SubscriptionManager.WFC_IMS_ROAMING_ENABLED,
2419 booleanToPropertyString(getBooleanCarrierConfig(
2420 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_ENABLED_BOOL)));
Brad Ebinger16417b42017-03-07 13:48:50 -08002421
2422 // Set VT to default
Malcolm Chen212ca652017-09-28 17:28:45 -07002423 SubscriptionManager.setSubscriptionProperty(getSubId(),
2424 SubscriptionManager.VT_IMS_ENABLED, booleanToPropertyString(true));
Brad Ebinger16417b42017-03-07 13:48:50 -08002425
2426 // Push settings to ImsConfig
Brad Ebingeref267192017-08-28 13:19:22 -07002427 updateImsServiceConfig(true);
Brad Ebinger16417b42017-03-07 13:48:50 -08002428 }
2429
Amit Mahajan24f7b162016-07-21 16:33:53 -07002430 private boolean isDataEnabled() {
2431 return SystemProperties.getBoolean(DATA_ENABLED_PROP, true);
2432 }
2433
Jack Yu643ffe42016-07-08 14:25:46 -07002434 /**
2435 * Set data enabled/disabled flag.
2436 * @param enabled True if data is enabled, otherwise disabled.
2437 */
2438 public void setDataEnabled(boolean enabled) {
2439 log("setDataEnabled: " + enabled);
Amit Mahajan24f7b162016-07-21 16:33:53 -07002440 SystemProperties.set(DATA_ENABLED_PROP, enabled ? TRUE : FALSE);
2441 }
2442
2443 private boolean isVolteProvisioned() {
2444 return SystemProperties.getBoolean(VOLTE_PROVISIONED_PROP, true);
2445 }
2446
2447 private void setVolteProvisionedProperty(boolean provisioned) {
2448 SystemProperties.set(VOLTE_PROVISIONED_PROP, provisioned ? TRUE : FALSE);
2449 }
2450
2451 private boolean isWfcProvisioned() {
2452 return SystemProperties.getBoolean(WFC_PROVISIONED_PROP, true);
2453 }
2454
2455 private void setWfcProvisionedProperty(boolean provisioned) {
2456 SystemProperties.set(WFC_PROVISIONED_PROP, provisioned ? TRUE : FALSE);
2457 }
2458
2459 private boolean isVtProvisioned() {
2460 return SystemProperties.getBoolean(VT_PROVISIONED_PROP, true);
2461 }
2462
2463 private void setVtProvisionedProperty(boolean provisioned) {
2464 SystemProperties.set(VT_PROVISIONED_PROP, provisioned ? TRUE : FALSE);
Jack Yu643ffe42016-07-08 14:25:46 -07002465 }
2466
Malcolm Chen212ca652017-09-28 17:28:45 -07002467 private static String booleanToPropertyString(boolean bool) {
2468 return bool ? "1" : "0";
2469 }
2470
2471
Jack Yu2f102bd2015-12-28 15:31:48 -08002472 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
2473 pw.println("ImsManager:");
2474 pw.println(" mPhoneId = " + mPhoneId);
2475 pw.println(" mConfigUpdated = " + mConfigUpdated);
Brad Ebinger16780ff2017-01-26 11:18:21 -08002476 pw.println(" mImsServiceProxy = " + mImsServiceProxy);
Amit Mahajan24f7b162016-07-21 16:33:53 -07002477 pw.println(" mDataEnabled = " + isDataEnabled());
Brad Ebingeref267192017-08-28 13:19:22 -07002478 pw.println(" ignoreDataEnabledChanged = " + getBooleanCarrierConfig(
Jack Yu57781852016-11-16 17:20:38 -08002479 CarrierConfigManager.KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS));
Jack Yu2f102bd2015-12-28 15:31:48 -08002480
Brad Ebingeref267192017-08-28 13:19:22 -07002481 pw.println(" isGbaValid = " + isGbaValid());
Jack Yu2f102bd2015-12-28 15:31:48 -08002482 pw.println(" isImsTurnOffAllowed = " + isImsTurnOffAllowed());
Brad Ebingeref267192017-08-28 13:19:22 -07002483 pw.println(" isNonTtyOrTtyOnVolteEnabled = " + isNonTtyOrTtyOnVolteEnabled());
Jack Yu2f102bd2015-12-28 15:31:48 -08002484
Brad Ebingeref267192017-08-28 13:19:22 -07002485 pw.println(" isVolteEnabledByPlatform = " + isVolteEnabledByPlatform());
2486 pw.println(" isVolteProvisionedOnDevice = " + isVolteProvisionedOnDevice());
Jack Yu2f102bd2015-12-28 15:31:48 -08002487 pw.println(" isEnhanced4gLteModeSettingEnabledByUser = " +
Brad Ebingeref267192017-08-28 13:19:22 -07002488 isEnhanced4gLteModeSettingEnabledByUser());
2489 pw.println(" isVtEnabledByPlatform = " + isVtEnabledByPlatform());
2490 pw.println(" isVtEnabledByUser = " + isVtEnabledByUser());
Jack Yu2f102bd2015-12-28 15:31:48 -08002491
Brad Ebingeref267192017-08-28 13:19:22 -07002492 pw.println(" isWfcEnabledByPlatform = " + isWfcEnabledByPlatform());
2493 pw.println(" isWfcEnabledByUser = " + isWfcEnabledByUser());
2494 pw.println(" getWfcMode = " + getWfcMode());
2495 pw.println(" isWfcRoamingEnabledByUser = " + isWfcRoamingEnabledByUser());
Jack Yu2f102bd2015-12-28 15:31:48 -08002496
Brad Ebingeref267192017-08-28 13:19:22 -07002497 pw.println(" isVtProvisionedOnDevice = " + isVtProvisionedOnDevice());
2498 pw.println(" isWfcProvisionedOnDevice = " + isWfcProvisionedOnDevice());
Jack Yu2f102bd2015-12-28 15:31:48 -08002499 pw.flush();
2500 }
Wink Savilleef36ef62014-06-11 08:39:38 -07002501}