blob: 0a0eb249570716539270176181e5b8b2c1eeb88c [file] [log] [blame]
Wink Savilleef36ef62014-06-11 08:39:38 -07001/*
2 * Copyright (c) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.ims;
18
Brad Ebinger172977a2018-01-16 09:36:56 -080019import android.annotation.Nullable;
Wink Savilleef36ef62014-06-11 08:39:38 -070020import android.app.PendingIntent;
21import android.content.Context;
Brad Ebinger172977a2018-01-16 09:36:56 -080022import android.os.Bundle;
Wink Savilleef36ef62014-06-11 08:39:38 -070023import android.os.IBinder;
Wink Savilleef36ef62014-06-11 08:39:38 -070024import android.os.Message;
Naveen Kalla525c3a22017-02-06 14:46:42 -080025import android.os.Parcel;
Jonathan Basseri2acea6f2015-07-01 15:00:38 -070026import android.os.PersistableBundle;
Wink Savilleef36ef62014-06-11 08:39:38 -070027import android.os.RemoteException;
Etan Cohenaf55a402014-09-04 22:34:41 -070028import android.os.SystemProperties;
Etan Cohen82f78122014-12-15 10:10:14 -080029import android.telecom.TelecomManager;
Junda Liue7663c02015-06-23 11:16:26 -070030import android.telephony.CarrierConfigManager;
Mohamed Abdalkadere1453f42018-01-19 19:48:31 -080031import android.telephony.ims.stub.ImsRegistrationImplBase;
Wink Savilleef36ef62014-06-11 08:39:38 -070032import android.telephony.Rlog;
Etan Cohen82f78122014-12-15 10:10:14 -080033import android.telephony.SubscriptionManager;
Etan Cohencfc784d2014-08-07 18:40:31 -070034import android.telephony.TelephonyManager;
Brad Ebinger190ed932018-01-23 13:41:32 -080035import android.telephony.ims.ImsCallProfile;
36import android.telephony.ims.ImsReasonInfo;
Brad Ebinger172977a2018-01-16 09:36:56 -080037import android.telephony.ims.aidl.IImsConfig;
38import android.telephony.ims.aidl.IImsSmsListener;
39import android.telephony.ims.feature.CapabilityChangeRequest;
40import android.telephony.ims.feature.ImsFeature;
41import android.telephony.ims.feature.MmTelFeature;
Hall Liue511a202017-08-17 15:49:58 -070042import android.util.Log;
Wink Savilleef36ef62014-06-11 08:39:38 -070043
44import com.android.ims.internal.IImsCallSession;
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -070045import com.android.ims.internal.IImsEcbm;
Tyler Gunn4d128b62016-04-13 15:44:38 -070046import com.android.ims.internal.IImsMultiEndpoint;
Wink Savilleef36ef62014-06-11 08:39:38 -070047import com.android.ims.internal.IImsUt;
Brad Ebinger190ed932018-01-23 13:41:32 -080048import android.telephony.ims.ImsCallSession;
Brad Ebinger16780ff2017-01-26 11:18:21 -080049import com.android.internal.annotations.VisibleForTesting;
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -050050
Jack Yu2f102bd2015-12-28 15:31:48 -080051import java.io.FileDescriptor;
52import java.io.PrintWriter;
Naveen Kalla525c3a22017-02-06 14:46:42 -080053import java.util.ArrayList;
Etan Cohend7727462014-07-12 14:54:10 -070054import java.util.HashMap;
Brad Ebinger16780ff2017-01-26 11:18:21 -080055import java.util.Set;
Malcolm Chen18837ff2017-10-25 17:05:41 -070056import java.util.concurrent.ConcurrentLinkedDeque;
Brad Ebinger44fd8af2017-12-14 14:24:02 -080057import java.util.concurrent.CopyOnWriteArraySet;
Etan Cohend7727462014-07-12 14:54:10 -070058
Wink Savilleef36ef62014-06-11 08:39:38 -070059/**
60 * Provides APIs for IMS services, such as initiating IMS calls, and provides access to
61 * the operator's IMS network. This class is the starting point for any IMS actions.
62 * You can acquire an instance of it with {@link #getInstance getInstance()}.</p>
63 * <p>The APIs in this class allows you to:</p>
64 *
65 * @hide
66 */
67public class ImsManager {
Etan Cohen19604c02014-08-11 14:32:57 -070068
Etan Cohenaf55a402014-09-04 22:34:41 -070069 /*
70 * Debug flag to override configuration flag
71 */
Etan Cohenb651fa52014-10-22 10:51:29 -070072 public static final String PROPERTY_DBG_VOLTE_AVAIL_OVERRIDE = "persist.dbg.volte_avail_ovr";
73 public static final int PROPERTY_DBG_VOLTE_AVAIL_OVERRIDE_DEFAULT = 0;
Etan Cohenea2b5832014-10-23 18:50:35 -070074 public static final String PROPERTY_DBG_VT_AVAIL_OVERRIDE = "persist.dbg.vt_avail_ovr";
75 public static final int PROPERTY_DBG_VT_AVAIL_OVERRIDE_DEFAULT = 0;
Etan Cohena00c9192014-12-23 15:02:29 -080076 public static final String PROPERTY_DBG_WFC_AVAIL_OVERRIDE = "persist.dbg.wfc_avail_ovr";
77 public static final int PROPERTY_DBG_WFC_AVAIL_OVERRIDE_DEFAULT = 0;
Meng Wang9352c432016-06-08 14:22:20 -070078 public static final String PROPERTY_DBG_ALLOW_IMS_OFF_OVERRIDE = "persist.dbg.allow_ims_off";
79 public static final int PROPERTY_DBG_ALLOW_IMS_OFF_OVERRIDE_DEFAULT = 0;
Etan Cohenaf55a402014-09-04 22:34:41 -070080
Wink Savilleef36ef62014-06-11 08:39:38 -070081 /**
Wink Savilleef36ef62014-06-11 08:39:38 -070082 * The result code to be sent back with the incoming call {@link PendingIntent}.
Brad Ebinger172977a2018-01-16 09:36:56 -080083 * @see #open(MmTelFeature.Listener)
Wink Savilleef36ef62014-06-11 08:39:38 -070084 */
85 public static final int INCOMING_CALL_RESULT_CODE = 101;
86
87 /**
88 * Key to retrieve the call ID from an incoming call intent.
Brad Ebinger172977a2018-01-16 09:36:56 -080089 * @see #open(MmTelFeature.Listener)
Wink Savilleef36ef62014-06-11 08:39:38 -070090 */
91 public static final String EXTRA_CALL_ID = "android:imsCallID";
92
93 /**
94 * Action to broadcast when ImsService is up.
95 * Internal use only.
Brad Ebinger16780ff2017-01-26 11:18:21 -080096 * @deprecated
Wink Savilleef36ef62014-06-11 08:39:38 -070097 * @hide
98 */
99 public static final String ACTION_IMS_SERVICE_UP =
100 "com.android.ims.IMS_SERVICE_UP";
101
102 /**
103 * Action to broadcast when ImsService is down.
104 * Internal use only.
Brad Ebinger16780ff2017-01-26 11:18:21 -0800105 * @deprecated
Wink Savilleef36ef62014-06-11 08:39:38 -0700106 * @hide
107 */
108 public static final String ACTION_IMS_SERVICE_DOWN =
109 "com.android.ims.IMS_SERVICE_DOWN";
110
111 /**
Pavel Zhamaitsiak0c2f15c2015-03-12 15:37:54 -0700112 * Action to broadcast when ImsService registration fails.
113 * Internal use only.
114 * @hide
115 */
116 public static final String ACTION_IMS_REGISTRATION_ERROR =
117 "com.android.ims.REGISTRATION_ERROR";
118
119 /**
Etan Cohend7727462014-07-12 14:54:10 -0700120 * Part of the ACTION_IMS_SERVICE_UP or _DOWN intents.
Etan Cohenabbd7882014-09-26 22:35:35 -0700121 * A long value; the phone ID corresponding to the IMS service coming up or down.
Etan Cohend7727462014-07-12 14:54:10 -0700122 * Internal use only.
123 * @hide
124 */
Etan Cohenabbd7882014-09-26 22:35:35 -0700125 public static final String EXTRA_PHONE_ID = "android:phone_id";
Etan Cohend7727462014-07-12 14:54:10 -0700126
127 /**
Wink Savilleef36ef62014-06-11 08:39:38 -0700128 * Action for the incoming call intent for the Phone app.
129 * Internal use only.
130 * @hide
131 */
132 public static final String ACTION_IMS_INCOMING_CALL =
133 "com.android.ims.IMS_INCOMING_CALL";
134
135 /**
136 * Part of the ACTION_IMS_INCOMING_CALL intents.
137 * An integer value; service identifier obtained from {@link ImsManager#open}.
138 * Internal use only.
139 * @hide
140 */
141 public static final String EXTRA_SERVICE_ID = "android:imsServiceId";
142
143 /**
144 * Part of the ACTION_IMS_INCOMING_CALL intents.
145 * An boolean value; Flag to indicate that the incoming call is a normal call or call for USSD.
146 * The value "true" indicates that the incoming call is for USSD.
147 * Internal use only.
148 * @hide
149 */
150 public static final String EXTRA_USSD = "android:ussd";
151
Shriram Ganeshd3adfad2015-05-31 10:06:15 -0700152 /**
153 * Part of the ACTION_IMS_INCOMING_CALL intents.
154 * A boolean value; Flag to indicate whether the call is an unknown
155 * dialing call. Such calls are originated by sending commands (like
156 * AT commands) directly to modem without Android involvement.
157 * Even though they are not incoming calls, they are propagated
158 * to Phone app using same ACTION_IMS_INCOMING_CALL intent.
159 * Internal use only.
160 * @hide
161 */
Anju Mathapati9c033792015-06-16 16:33:16 -0700162 public static final String EXTRA_IS_UNKNOWN_CALL = "android:isUnknown";
Shriram Ganeshd3adfad2015-05-31 10:06:15 -0700163
Malcolm Chen18837ff2017-10-25 17:05:41 -0700164 private static final int SYSTEM_PROPERTY_NOT_SET = -1;
165
166 // -1 indicates a subscriptionProperty value that is never set.
167 private static final int SUB_PROPERTY_NOT_INITIALIZED = -1;
168
Wink Savilleef36ef62014-06-11 08:39:38 -0700169 private static final String TAG = "ImsManager";
170 private static final boolean DBG = true;
171
Wink Saville1e5a38a2014-10-23 10:24:46 -0700172 private static HashMap<Integer, ImsManager> sImsManagerInstances =
173 new HashMap<Integer, ImsManager>();
Etan Cohend7727462014-07-12 14:54:10 -0700174
Wink Savilleef36ef62014-06-11 08:39:38 -0700175 private Context mContext;
Brad Ebinger16417b42017-03-07 13:48:50 -0800176 private CarrierConfigManager mConfigManager;
Etan Cohenabbd7882014-09-26 22:35:35 -0700177 private int mPhoneId;
Brad Ebinger16780ff2017-01-26 11:18:21 -0800178 private final boolean mConfigDynamicBind;
Brad Ebinger172977a2018-01-16 09:36:56 -0800179 private @Nullable MmTelFeatureConnection mMmTelFeatureConnection = null;
Wink Savilleef36ef62014-06-11 08:39:38 -0700180 private ImsServiceDeathRecipient mDeathRecipient = new ImsServiceDeathRecipient();
181 // Ut interface for the supplementary service configuration
182 private ImsUt mUt = null;
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -0500183 // Interface to get/set ims config items
184 private ImsConfig mConfig = null;
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -0700185 private boolean mConfigUpdated = false;
Wink Savilleef36ef62014-06-11 08:39:38 -0700186
Pavel Zhamaitsiakf4b90322016-01-26 14:34:09 -0800187 private ImsConfigListener mImsConfigListener;
188
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -0700189 // ECBM interface
190 private ImsEcbm mEcbm = null;
191
Tyler Gunn4d128b62016-04-13 15:44:38 -0700192 private ImsMultiEndpoint mMultiEndpoint = null;
193
Brad Ebinger172977a2018-01-16 09:36:56 -0800194 private Set<MmTelFeatureConnection.IFeatureUpdate> mStatusCallbacks =
195 new CopyOnWriteArraySet<>();
Brad Ebinger16780ff2017-01-26 11:18:21 -0800196
Amit Mahajan24f7b162016-07-21 16:33:53 -0700197 public static final String TRUE = "true";
198 public static final String FALSE = "false";
Jack Yu643ffe42016-07-08 14:25:46 -0700199
Naveen Kalla525c3a22017-02-06 14:46:42 -0800200 // mRecentDisconnectReasons stores the last 16 disconnect reasons
201 private static final int MAX_RECENT_DISCONNECT_REASONS = 16;
202 private ConcurrentLinkedDeque<ImsReasonInfo> mRecentDisconnectReasons =
203 new ConcurrentLinkedDeque<>();
204
Wink Savilleef36ef62014-06-11 08:39:38 -0700205 /**
206 * Gets a manager instance.
207 *
208 * @param context application context for creating the manager object
Etan Cohenabbd7882014-09-26 22:35:35 -0700209 * @param phoneId the phone ID for the IMS Service
210 * @return the manager instance corresponding to the phoneId
Wink Savilleef36ef62014-06-11 08:39:38 -0700211 */
Etan Cohenabbd7882014-09-26 22:35:35 -0700212 public static ImsManager getInstance(Context context, int phoneId) {
Etan Cohend7727462014-07-12 14:54:10 -0700213 synchronized (sImsManagerInstances) {
Naveen Kalla525c3a22017-02-06 14:46:42 -0800214 if (sImsManagerInstances.containsKey(phoneId)) {
Brad Ebingerff097922017-06-19 15:43:08 -0700215 ImsManager m = sImsManagerInstances.get(phoneId);
216 // May be null for some tests
217 if (m != null) {
218 m.connectIfServiceIsAvailable();
219 }
220 return m;
Naveen Kalla525c3a22017-02-06 14:46:42 -0800221 }
Wink Savilleef36ef62014-06-11 08:39:38 -0700222
Etan Cohenabbd7882014-09-26 22:35:35 -0700223 ImsManager mgr = new ImsManager(context, phoneId);
224 sImsManagerInstances.put(phoneId, mgr);
Etan Cohend7727462014-07-12 14:54:10 -0700225
226 return mgr;
227 }
Wink Savilleef36ef62014-06-11 08:39:38 -0700228 }
229
Etan Cohen45b5f312014-08-19 15:55:08 -0700230 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800231 * Returns the user configuration of Enhanced 4G LTE Mode setting.
232 *
233 * @deprecated Doesn't support MSIM devices. Use
Brad Ebinger479f52c2017-08-28 13:19:22 -0700234 * {@link #isEnhanced4gLteModeSettingEnabledByUser()} instead.
Etan Cohen45b5f312014-08-19 15:55:08 -0700235 */
236 public static boolean isEnhanced4gLteModeSettingEnabledByUser(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700237 ImsManager mgr = ImsManager.getInstance(context,
238 SubscriptionManager.getDefaultVoicePhoneId());
239 if (mgr != null) {
240 return mgr.isEnhanced4gLteModeSettingEnabledByUser();
Sungmin Choi2f1af952016-02-01 17:15:35 +0900241 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700242 loge("isEnhanced4gLteModeSettingEnabledByUser: ImsManager null, returning default value.");
243 return false;
Etan Cohen45b5f312014-08-19 15:55:08 -0700244 }
245
246 /**
manabu, shimoda96aee542017-10-06 15:39:36 +0900247 * Returns the user configuration of Enhanced 4G LTE Mode setting for slot. If the option is
248 * not editable ({@link CarrierConfigManager#KEY_EDITABLE_ENHANCED_4G_LTE_BOOL} is false), or
249 * the setting is not initialized, this method will return default value specified by
250 * {@link CarrierConfigManager#KEY_ENHANCED_4G_LTE_ON_BY_DEFAULT_BOOL}.
251 *
252 * Note that even if the setting was set, it may no longer be editable. If this is the case we
253 * return the default value.
Brad Ebinger16417b42017-03-07 13:48:50 -0800254 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700255 public boolean isEnhanced4gLteModeSettingEnabledByUser() {
Malcolm Chen212ca652017-09-28 17:28:45 -0700256 int setting = SubscriptionManager.getIntegerSubscriptionProperty(
257 getSubId(), SubscriptionManager.ENHANCED_4G_MODE_ENABLED,
258 SUB_PROPERTY_NOT_INITIALIZED, mContext);
manabu, shimoda96aee542017-10-06 15:39:36 +0900259 boolean onByDefault = getBooleanCarrierConfig(
260 CarrierConfigManager.KEY_ENHANCED_4G_LTE_ON_BY_DEFAULT_BOOL);
Malcolm Chen212ca652017-09-28 17:28:45 -0700261
manabu, shimoda96aee542017-10-06 15:39:36 +0900262 // If Enhanced 4G LTE Mode is uneditable or not initialized, we use the default value
263 if (!getBooleanCarrierConfig(CarrierConfigManager.KEY_EDITABLE_ENHANCED_4G_LTE_BOOL)
264 || setting == SUB_PROPERTY_NOT_INITIALIZED) {
265 return onByDefault;
266 } else {
267 return (setting == ImsConfig.FeatureValueConstants.ON);
268 }
Brad Ebinger16417b42017-03-07 13:48:50 -0800269 }
270
271 /**
272 * Change persistent Enhanced 4G LTE Mode setting.
273 *
Brad Ebinger479f52c2017-08-28 13:19:22 -0700274 * @deprecated Doesn't support MSIM devices. Use {@link #setEnhanced4gLteModeSetting(boolean)}
Brad Ebinger16417b42017-03-07 13:48:50 -0800275 * instead.
Etan Cohen82f78122014-12-15 10:10:14 -0800276 */
277 public static void setEnhanced4gLteModeSetting(Context context, boolean enabled) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700278 ImsManager mgr = ImsManager.getInstance(context,
279 SubscriptionManager.getDefaultVoicePhoneId());
280 if (mgr != null) {
281 mgr.setEnhanced4gLteModeSetting(enabled);
Etan Cohen82f78122014-12-15 10:10:14 -0800282 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700283 loge("setEnhanced4gLteModeSetting: ImsManager null, value not set.");
Etan Cohen82f78122014-12-15 10:10:14 -0800284 }
285
286 /**
manabu, shimoda96aee542017-10-06 15:39:36 +0900287 * Change persistent Enhanced 4G LTE Mode setting. If the option is not editable
Brad Ebinger16417b42017-03-07 13:48:50 -0800288 * ({@link CarrierConfigManager#KEY_EDITABLE_ENHANCED_4G_LTE_BOOL} is false), this method will
manabu, shimoda96aee542017-10-06 15:39:36 +0900289 * set the setting to the default value specified by
290 * {@link CarrierConfigManager#KEY_ENHANCED_4G_LTE_ON_BY_DEFAULT_BOOL}.
Brad Ebinger16417b42017-03-07 13:48:50 -0800291 *
292 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700293 public void setEnhanced4gLteModeSetting(boolean enabled) {
manabu, shimoda96aee542017-10-06 15:39:36 +0900294 // If editable=false, we must keep default advanced 4G mode.
295 if (!getBooleanCarrierConfig(CarrierConfigManager.KEY_EDITABLE_ENHANCED_4G_LTE_BOOL)) {
296 enabled = getBooleanCarrierConfig(
297 CarrierConfigManager.KEY_ENHANCED_4G_LTE_ON_BY_DEFAULT_BOOL);
298 }
Brad Ebinger16417b42017-03-07 13:48:50 -0800299
Malcolm Chen212ca652017-09-28 17:28:45 -0700300 int prevSetting = SubscriptionManager.getIntegerSubscriptionProperty(
301 getSubId(), SubscriptionManager.ENHANCED_4G_MODE_ENABLED,
302 SUB_PROPERTY_NOT_INITIALIZED, mContext);
Brad Ebinger16417b42017-03-07 13:48:50 -0800303
manabu, shimoda96aee542017-10-06 15:39:36 +0900304 if (prevSetting != (enabled ?
305 ImsConfig.FeatureValueConstants.ON :
306 ImsConfig.FeatureValueConstants.OFF)) {
Malcolm Chen212ca652017-09-28 17:28:45 -0700307 SubscriptionManager.setSubscriptionProperty(getSubId(),
308 SubscriptionManager.ENHANCED_4G_MODE_ENABLED, booleanToPropertyString(enabled));
309 if (isNonTtyOrTtyOnVolteEnabled()) {
310 try {
311 setAdvanced4GMode(enabled);
312 } catch (ImsException ie) {
313 // do nothing
314 }
Brad Ebinger16417b42017-03-07 13:48:50 -0800315 }
316 }
317 }
318
319 /**
Etan Cohen82f78122014-12-15 10:10:14 -0800320 * Indicates whether the call is non-TTY or if TTY - whether TTY on VoLTE is
321 * supported.
Brad Ebinger16417b42017-03-07 13:48:50 -0800322 * @deprecated Does not support MSIM devices. Please use
Brad Ebinger479f52c2017-08-28 13:19:22 -0700323 * {@link #isNonTtyOrTtyOnVolteEnabled()} instead.
Etan Cohen82f78122014-12-15 10:10:14 -0800324 */
325 public static boolean isNonTtyOrTtyOnVolteEnabled(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700326 ImsManager mgr = ImsManager.getInstance(context,
327 SubscriptionManager.getDefaultVoicePhoneId());
328 if (mgr != null) {
329 return mgr.isNonTtyOrTtyOnVolteEnabled();
330 }
331 loge("isNonTtyOrTtyOnVolteEnabled: ImsManager null, returning default value.");
332 return false;
333 }
334
335 /**
336 * Indicates whether the call is non-TTY or if TTY - whether TTY on VoLTE is
337 * supported on a per slot basis.
338 */
339 public boolean isNonTtyOrTtyOnVolteEnabled() {
340 if (getBooleanCarrierConfig(
fionaxu5803ef02016-03-08 11:48:48 -0800341 CarrierConfigManager.KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL)) {
Etan Cohen82f78122014-12-15 10:10:14 -0800342 return true;
343 }
344
Brad Ebinger479f52c2017-08-28 13:19:22 -0700345 TelecomManager tm = (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
Hall Liue511a202017-08-17 15:49:58 -0700346 if (tm == null) {
347 Log.w(TAG, "isNonTtyOrTtyOnVolteEnabled: telecom not available");
348 return true;
349 }
350 return tm.getCurrentTtyMode() == TelecomManager.TTY_MODE_OFF;
Etan Cohen82f78122014-12-15 10:10:14 -0800351 }
352
353 /**
Etan Cohenea2b5832014-10-23 18:50:35 -0700354 * Returns a platform configuration for VoLTE which may override the user setting.
Brad Ebinger16417b42017-03-07 13:48:50 -0800355 * @deprecated Does not support MSIM devices. Please use
Brad Ebinger479f52c2017-08-28 13:19:22 -0700356 * {@link #isVolteEnabledByPlatform()} instead.
Etan Cohen45b5f312014-08-19 15:55:08 -0700357 */
Etan Cohenea2b5832014-10-23 18:50:35 -0700358 public static boolean isVolteEnabledByPlatform(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700359 ImsManager mgr = ImsManager.getInstance(context,
360 SubscriptionManager.getDefaultVoicePhoneId());
361 if (mgr != null) {
362 return mgr.isVolteEnabledByPlatform();
Etan Cohenaf55a402014-09-04 22:34:41 -0700363 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700364 loge("isVolteEnabledByPlatform: ImsManager null, returning default value.");
365 return false;
Etan Cohenb5388a32014-11-26 11:57:47 -0800366 }
367
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700368 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800369 * Returns a platform configuration for VoLTE which may override the user setting on a per Slot
370 * basis.
371 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700372 public boolean isVolteEnabledByPlatform() {
Malcolm Chen18837ff2017-10-25 17:05:41 -0700373 // We first read the per slot value. If doesn't exist, we read the general value. If still
374 // doesn't exist, we use the hardcoded default value.
375 if (SystemProperties.getInt(
376 PROPERTY_DBG_VOLTE_AVAIL_OVERRIDE + Integer.toString(mPhoneId),
377 SYSTEM_PROPERTY_NOT_SET) == 1 ||
378 SystemProperties.getInt(PROPERTY_DBG_VOLTE_AVAIL_OVERRIDE,
379 SYSTEM_PROPERTY_NOT_SET) == 1) {
Brad Ebinger16417b42017-03-07 13:48:50 -0800380 return true;
381 }
382
383 return mContext.getResources().getBoolean(
384 com.android.internal.R.bool.config_device_volte_available)
Malcolm Chen212ca652017-09-28 17:28:45 -0700385 && getBooleanCarrierConfig(CarrierConfigManager.KEY_CARRIER_VOLTE_AVAILABLE_BOOL)
Brad Ebinger479f52c2017-08-28 13:19:22 -0700386 && isGbaValid();
Brad Ebinger16417b42017-03-07 13:48:50 -0800387 }
388
389 /**
390 * Indicates whether VoLTE is provisioned on device.
391 *
392 * @deprecated Does not support MSIM devices. Please use
Brad Ebinger479f52c2017-08-28 13:19:22 -0700393 * {@link #isVolteProvisionedOnDevice()} instead.
Etan Cohenb5388a32014-11-26 11:57:47 -0800394 */
395 public static boolean isVolteProvisionedOnDevice(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700396 ImsManager mgr = ImsManager.getInstance(context,
397 SubscriptionManager.getDefaultVoicePhoneId());
398 if (mgr != null) {
399 return mgr.isVolteProvisionedOnDevice();
Etan Cohenb5388a32014-11-26 11:57:47 -0800400 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700401 loge("isVolteProvisionedOnDevice: ImsManager null, returning default value.");
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700402 return true;
403 }
404
405 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800406 * Indicates whether VoLTE is provisioned on this slot.
407 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700408 public boolean isVolteProvisionedOnDevice() {
409 if (getBooleanCarrierConfig(
Brad Ebinger16417b42017-03-07 13:48:50 -0800410 CarrierConfigManager.KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL)) {
411 return isVolteProvisioned();
412 }
413
414 return true;
415 }
416
417 /**
Meng Wang54fd41a2017-04-12 11:44:47 -0700418 * Indicates whether VoWifi is provisioned on device.
419 *
420 * When CarrierConfig KEY_CARRIER_VOLTE_OVERRIDE_WFC_PROVISIONING_BOOL is true, and VoLTE is not
421 * provisioned on device, this method returns false.
Brad Ebinger16417b42017-03-07 13:48:50 -0800422 *
423 * @deprecated Does not support MSIM devices. Please use
Brad Ebinger479f52c2017-08-28 13:19:22 -0700424 * {@link #isWfcProvisionedOnDevice()} instead.
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700425 */
426 public static boolean isWfcProvisionedOnDevice(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700427 ImsManager mgr = ImsManager.getInstance(context,
428 SubscriptionManager.getDefaultVoicePhoneId());
429 if (mgr != null) {
430 return mgr.isWfcProvisionedOnDevice();
Meng Wang54fd41a2017-04-12 11:44:47 -0700431 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700432 loge("isWfcProvisionedOnDevice: ImsManager null, returning default value.");
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700433 return true;
434 }
435
436 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800437 * Indicates whether VoWifi is provisioned on slot.
Meng Wang54fd41a2017-04-12 11:44:47 -0700438 *
439 * When CarrierConfig KEY_CARRIER_VOLTE_OVERRIDE_WFC_PROVISIONING_BOOL is true, and VoLTE is not
440 * provisioned on device, this method returns false.
Brad Ebinger16417b42017-03-07 13:48:50 -0800441 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700442 public boolean isWfcProvisionedOnDevice() {
443 if (getBooleanCarrierConfig(
Meng Wang54fd41a2017-04-12 11:44:47 -0700444 CarrierConfigManager.KEY_CARRIER_VOLTE_OVERRIDE_WFC_PROVISIONING_BOOL)) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700445 if (!isVolteProvisionedOnDevice()) {
Meng Wang54fd41a2017-04-12 11:44:47 -0700446 return false;
447 }
448 }
449
Brad Ebinger479f52c2017-08-28 13:19:22 -0700450 if (getBooleanCarrierConfig(
Brad Ebinger16417b42017-03-07 13:48:50 -0800451 CarrierConfigManager.KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL)) {
Meng Wang54fd41a2017-04-12 11:44:47 -0700452 return isWfcProvisioned();
Brad Ebinger16417b42017-03-07 13:48:50 -0800453 }
454
455 return true;
456 }
457
458 /**
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700459 * Indicates whether VT is provisioned on device
Brad Ebinger16417b42017-03-07 13:48:50 -0800460 *
461 * @deprecated Does not support MSIM devices. Please use
Brad Ebinger479f52c2017-08-28 13:19:22 -0700462 * {@link #isVtProvisionedOnDevice()} instead.
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700463 */
464 public static boolean isVtProvisionedOnDevice(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700465 ImsManager mgr = ImsManager.getInstance(context,
466 SubscriptionManager.getDefaultVoicePhoneId());
467 if (mgr != null) {
468 return mgr.isVtProvisionedOnDevice();
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700469 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700470 loge("isVtProvisionedOnDevice: ImsManager null, returning default value.");
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700471 return true;
Etan Cohenb651fa52014-10-22 10:51:29 -0700472 }
473
Etan Cohenea2b5832014-10-23 18:50:35 -0700474 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800475 * Indicates whether VT is provisioned on slot.
476 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700477 public boolean isVtProvisionedOnDevice() {
478 if (getBooleanCarrierConfig(
Brad Ebinger16417b42017-03-07 13:48:50 -0800479 CarrierConfigManager.KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL)) {
480 return isVtProvisioned();
481 }
482
483 return true;
484 }
485
486 /**
Etan Cohenea2b5832014-10-23 18:50:35 -0700487 * Returns a platform configuration for VT which may override the user setting.
488 *
489 * Note: VT presumes that VoLTE is enabled (these are configuration settings
490 * which must be done correctly).
Brad Ebinger16417b42017-03-07 13:48:50 -0800491 *
492 * @deprecated Does not support MSIM devices. Please use
Brad Ebinger479f52c2017-08-28 13:19:22 -0700493 * {@link #isVtEnabledByPlatform()} instead.
Etan Cohenea2b5832014-10-23 18:50:35 -0700494 */
Etan Cohenb651fa52014-10-22 10:51:29 -0700495 public static boolean isVtEnabledByPlatform(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700496 ImsManager mgr = ImsManager.getInstance(context,
497 SubscriptionManager.getDefaultVoicePhoneId());
498 if (mgr != null) {
499 return mgr.isVtEnabledByPlatform();
Etan Cohenea2b5832014-10-23 18:50:35 -0700500 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700501 loge("isVtEnabledByPlatform: ImsManager null, returning default value.");
502 return false;
Etan Cohen45b5f312014-08-19 15:55:08 -0700503 }
504
Etan Cohena00c9192014-12-23 15:02:29 -0800505 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800506 * Returns a platform configuration for VT which may override the user setting.
507 *
508 * Note: VT presumes that VoLTE is enabled (these are configuration settings
509 * which must be done correctly).
510 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700511 public boolean isVtEnabledByPlatform() {
Malcolm Chen18837ff2017-10-25 17:05:41 -0700512 // We first read the per slot value. If doesn't exist, we read the general value. If still
513 // doesn't exist, we use the hardcoded default value.
514 if (SystemProperties.getInt(PROPERTY_DBG_VT_AVAIL_OVERRIDE +
515 Integer.toString(mPhoneId), SYSTEM_PROPERTY_NOT_SET) == 1 ||
516 SystemProperties.getInt(
517 PROPERTY_DBG_VT_AVAIL_OVERRIDE, SYSTEM_PROPERTY_NOT_SET) == 1) {
Brad Ebinger16417b42017-03-07 13:48:50 -0800518 return true;
519 }
520
521 return mContext.getResources().getBoolean(
522 com.android.internal.R.bool.config_device_vt_available) &&
Malcolm Chen212ca652017-09-28 17:28:45 -0700523 getBooleanCarrierConfig(CarrierConfigManager.KEY_CARRIER_VT_AVAILABLE_BOOL) &&
Brad Ebinger479f52c2017-08-28 13:19:22 -0700524 isGbaValid();
Brad Ebinger16417b42017-03-07 13:48:50 -0800525 }
526
527 /**
Etan Cohena7d32e82015-05-04 18:02:09 -0700528 * Returns the user configuration of VT setting
Brad Ebinger16417b42017-03-07 13:48:50 -0800529 * @deprecated Does not support MSIM devices. Please use
Brad Ebinger479f52c2017-08-28 13:19:22 -0700530 * {@link #isVtEnabledByUser()} instead.
Etan Cohena7d32e82015-05-04 18:02:09 -0700531 */
532 public static boolean isVtEnabledByUser(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700533 ImsManager mgr = ImsManager.getInstance(context,
534 SubscriptionManager.getDefaultVoicePhoneId());
535 if (mgr != null) {
536 return mgr.isVtEnabledByUser();
537 }
538 loge("isVtEnabledByUser: ImsManager null, returning default value.");
539 return false;
Etan Cohena7d32e82015-05-04 18:02:09 -0700540 }
541
542 /**
Malcolm Chen212ca652017-09-28 17:28:45 -0700543 * Returns the user configuration of VT setting per slot. If not set, it
544 * returns true as default value.
Brad Ebinger16417b42017-03-07 13:48:50 -0800545 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700546 public boolean isVtEnabledByUser() {
Malcolm Chen212ca652017-09-28 17:28:45 -0700547 int setting = SubscriptionManager.getIntegerSubscriptionProperty(
548 getSubId(), SubscriptionManager.VT_IMS_ENABLED,
549 SUB_PROPERTY_NOT_INITIALIZED, mContext);
550
551 // If it's never set, by default we return true.
manabu, shimoda96aee542017-10-06 15:39:36 +0900552 return (setting == SUB_PROPERTY_NOT_INITIALIZED
553 || setting == ImsConfig.FeatureValueConstants.ON);
Brad Ebinger16417b42017-03-07 13:48:50 -0800554 }
555
556 /**
Etan Cohena7d32e82015-05-04 18:02:09 -0700557 * Change persistent VT enabled setting
Brad Ebinger16417b42017-03-07 13:48:50 -0800558 *
Brad Ebinger479f52c2017-08-28 13:19:22 -0700559 * @deprecated Does not support MSIM devices. Please use {@link #setVtSetting(boolean)} instead.
Etan Cohena7d32e82015-05-04 18:02:09 -0700560 */
561 public static void setVtSetting(Context context, boolean enabled) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700562 ImsManager mgr = ImsManager.getInstance(context,
Etan Cohena7d32e82015-05-04 18:02:09 -0700563 SubscriptionManager.getDefaultVoicePhoneId());
Brad Ebinger479f52c2017-08-28 13:19:22 -0700564 if (mgr != null) {
565 mgr.setVtSetting(enabled);
Etan Cohena7d32e82015-05-04 18:02:09 -0700566 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700567 loge("setVtSetting: ImsManager null, can not set value.");
Etan Cohena7d32e82015-05-04 18:02:09 -0700568 }
569
Brad Ebinger16417b42017-03-07 13:48:50 -0800570 /**
571 * Change persistent VT enabled setting for slot.
572 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700573 public void setVtSetting(boolean enabled) {
Brad Ebinger172977a2018-01-16 09:36:56 -0800574 SubscriptionManager.setSubscriptionProperty(getSubId(), SubscriptionManager.VT_IMS_ENABLED,
Malcolm Chen212ca652017-09-28 17:28:45 -0700575 booleanToPropertyString(enabled));
Brad Ebinger172977a2018-01-16 09:36:56 -0800576
Brad Ebinger16417b42017-03-07 13:48:50 -0800577 try {
Brad Ebinger172977a2018-01-16 09:36:56 -0800578 changeMmTelCapability(MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VIDEO,
579 ImsRegistrationImplBase.REGISTRATION_TECH_LTE, enabled);
Brad Ebinger16417b42017-03-07 13:48:50 -0800580
581 if (enabled) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700582 log("setVtSetting(b) : turnOnIms");
Brad Ebinger16417b42017-03-07 13:48:50 -0800583 turnOnIms();
Brad Ebinger479f52c2017-08-28 13:19:22 -0700584 } else if (isVolteEnabledByPlatform()
585 && (!isVolteEnabledByPlatform()
586 || !isEnhanced4gLteModeSettingEnabledByUser())) {
587 log("setVtSetting(b) : imsServiceAllowTurnOff -> turnOffIms");
Brad Ebinger16417b42017-03-07 13:48:50 -0800588 turnOffIms();
589 }
Brad Ebinger172977a2018-01-16 09:36:56 -0800590 } catch (ImsException | RemoteException e) {
591 // The ImsService is down. Since the SubscriptionManager already recorded the user's
592 // preference, it will be resent in updateImsServiceConfig when the ImsPhoneCallTracker
593 // reconnects.
Brad Ebinger479f52c2017-08-28 13:19:22 -0700594 loge("setVtSetting(b): ", e);
Brad Ebinger16417b42017-03-07 13:48:50 -0800595 }
596 }
597
598 /**
Meng Wang9352c432016-06-08 14:22:20 -0700599 * Returns whether turning off ims is allowed by platform.
600 * The platform property may override the carrier config.
Brad Ebinger16417b42017-03-07 13:48:50 -0800601 *
602 * @deprecated Does not support MSIM devices. Please use
Brad Ebinger479f52c2017-08-28 13:19:22 -0700603 * {@link #isTurnOffImsAllowedByPlatform()} instead.
Meng Wang9352c432016-06-08 14:22:20 -0700604 */
605 private static boolean isTurnOffImsAllowedByPlatform(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700606 ImsManager mgr = ImsManager.getInstance(context,
607 SubscriptionManager.getDefaultVoicePhoneId());
608 if (mgr != null) {
609 return mgr.isTurnOffImsAllowedByPlatform();
Meng Wang9352c432016-06-08 14:22:20 -0700610 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700611 loge("isTurnOffImsAllowedByPlatform: ImsManager null, returning default value.");
612 return true;
Meng Wang9352c432016-06-08 14:22:20 -0700613 }
614
Etan Cohena7d32e82015-05-04 18:02:09 -0700615 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800616 * Returns whether turning off ims is allowed by platform.
617 * The platform property may override the carrier config.
618 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700619 private boolean isTurnOffImsAllowedByPlatform() {
Malcolm Chen18837ff2017-10-25 17:05:41 -0700620 // We first read the per slot value. If doesn't exist, we read the general value. If still
621 // doesn't exist, we use the hardcoded default value.
622 if (SystemProperties.getInt(PROPERTY_DBG_ALLOW_IMS_OFF_OVERRIDE +
623 Integer.toString(mPhoneId), SYSTEM_PROPERTY_NOT_SET) == 1 ||
624 SystemProperties.getInt(
625 PROPERTY_DBG_ALLOW_IMS_OFF_OVERRIDE, SYSTEM_PROPERTY_NOT_SET) == 1) {
Brad Ebinger16417b42017-03-07 13:48:50 -0800626 return true;
627 }
Malcolm Chen18837ff2017-10-25 17:05:41 -0700628
Brad Ebinger479f52c2017-08-28 13:19:22 -0700629 return getBooleanCarrierConfig(
Brad Ebinger16417b42017-03-07 13:48:50 -0800630 CarrierConfigManager.KEY_CARRIER_ALLOW_TURNOFF_IMS_BOOL);
631 }
632
633 /**
Etan Cohena00c9192014-12-23 15:02:29 -0800634 * Returns the user configuration of WFC setting
Brad Ebinger16417b42017-03-07 13:48:50 -0800635 *
636 * @deprecated Does not support MSIM devices. Please use
Brad Ebinger479f52c2017-08-28 13:19:22 -0700637 * {@link #isWfcEnabledByUser()} instead.
Etan Cohena00c9192014-12-23 15:02:29 -0800638 */
639 public static boolean isWfcEnabledByUser(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700640 ImsManager mgr = ImsManager.getInstance(context,
641 SubscriptionManager.getDefaultVoicePhoneId());
642 if (mgr != null) {
643 return mgr.isWfcEnabledByUser();
644 }
645 loge("isWfcEnabledByUser: ImsManager null, returning default value.");
646 return true;
Etan Cohena00c9192014-12-23 15:02:29 -0800647 }
648
649 /**
Malcolm Chen212ca652017-09-28 17:28:45 -0700650 * Returns the user configuration of WFC setting for slot. If not set, it
651 * queries CarrierConfig value as default.
Brad Ebinger16417b42017-03-07 13:48:50 -0800652 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700653 public boolean isWfcEnabledByUser() {
Malcolm Chen212ca652017-09-28 17:28:45 -0700654 int setting = SubscriptionManager.getIntegerSubscriptionProperty(
655 getSubId(), SubscriptionManager.WFC_IMS_ENABLED,
656 SUB_PROPERTY_NOT_INITIALIZED, mContext);
657
658 // SUB_PROPERTY_NOT_INITIALIZED indicates it's never set in sub db.
659 if (setting == SUB_PROPERTY_NOT_INITIALIZED) {
660 return getBooleanCarrierConfig(
661 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ENABLED_BOOL);
662 } else {
manabu, shimoda96aee542017-10-06 15:39:36 +0900663 return setting == ImsConfig.FeatureValueConstants.ON;
Malcolm Chen212ca652017-09-28 17:28:45 -0700664 }
Brad Ebinger16417b42017-03-07 13:48:50 -0800665 }
666
667 /**
668 * Change persistent WFC enabled setting.
669 * @deprecated Does not support MSIM devices. Please use
Brad Ebinger479f52c2017-08-28 13:19:22 -0700670 * {@link #setWfcSetting} instead.
Etan Cohena00c9192014-12-23 15:02:29 -0800671 */
672 public static void setWfcSetting(Context context, boolean enabled) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700673 ImsManager mgr = ImsManager.getInstance(context,
Etan Cohena00c9192014-12-23 15:02:29 -0800674 SubscriptionManager.getDefaultVoicePhoneId());
Brad Ebinger479f52c2017-08-28 13:19:22 -0700675 if (mgr != null) {
676 mgr.setWfcSetting(enabled);
Etan Cohena00c9192014-12-23 15:02:29 -0800677 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700678 loge("setWfcSetting: ImsManager null, can not set value.");
Etan Cohena00c9192014-12-23 15:02:29 -0800679 }
680
681 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800682 * Change persistent WFC enabled setting for slot.
683 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700684 public void setWfcSetting(boolean enabled) {
Malcolm Chen212ca652017-09-28 17:28:45 -0700685 SubscriptionManager.setSubscriptionProperty(getSubId(),
686 SubscriptionManager.WFC_IMS_ENABLED, booleanToPropertyString(enabled));
Brad Ebinger16417b42017-03-07 13:48:50 -0800687
Brad Ebinger479f52c2017-08-28 13:19:22 -0700688 setWfcNonPersistent(enabled, getWfcMode());
Meng Wang51c09072017-03-27 10:47:45 -0700689 }
690
691 /**
692 * Non-persistently change WFC enabled setting and WFC mode for slot
693 *
694 * @param wfcMode The WFC preference if WFC is enabled
695 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700696 public void setWfcNonPersistent(boolean enabled, int wfcMode) {
Meng Wang51c09072017-03-27 10:47:45 -0700697 // Force IMS to register over LTE when turning off WFC
698 int imsWfcModeFeatureValue =
699 enabled ? wfcMode : ImsConfig.WfcModeFeatureValueConstants.CELLULAR_PREFERRED;
700
Brad Ebinger16417b42017-03-07 13:48:50 -0800701 try {
Brad Ebinger172977a2018-01-16 09:36:56 -0800702 changeMmTelCapability(MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE,
703 ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN, enabled);
Brad Ebinger16417b42017-03-07 13:48:50 -0800704
705 if (enabled) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700706 log("setWfcSetting() : turnOnIms");
Brad Ebinger16417b42017-03-07 13:48:50 -0800707 turnOnIms();
Brad Ebinger479f52c2017-08-28 13:19:22 -0700708 } else if (isTurnOffImsAllowedByPlatform()
709 && (!isVolteEnabledByPlatform()
710 || !isEnhanced4gLteModeSettingEnabledByUser())) {
711 log("setWfcSetting() : imsServiceAllowTurnOff -> turnOffIms");
Brad Ebinger16417b42017-03-07 13:48:50 -0800712 turnOffIms();
713 }
714
Brad Ebinger479f52c2017-08-28 13:19:22 -0700715 setWfcModeInternal(imsWfcModeFeatureValue);
Brad Ebinger172977a2018-01-16 09:36:56 -0800716 } catch (ImsException | RemoteException e) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700717 loge("setWfcSetting(): ", e);
Brad Ebinger16417b42017-03-07 13:48:50 -0800718 }
719 }
720
721 /**
722 * Returns the user configuration of WFC preference setting.
723 *
Malcolm Chen212ca652017-09-28 17:28:45 -0700724 * @deprecated Doesn't support MSIM devices. Use {@link #getWfcMode(boolean roaming)} instead.
Etan Cohena00c9192014-12-23 15:02:29 -0800725 */
726 public static int getWfcMode(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700727 ImsManager mgr = ImsManager.getInstance(context,
728 SubscriptionManager.getDefaultVoicePhoneId());
729 if (mgr != null) {
730 return mgr.getWfcMode();
731 }
732 loge("getWfcMode: ImsManager null, returning default value.");
733 return ImsConfig.WfcModeFeatureValueConstants.WIFI_ONLY;
Etan Cohena00c9192014-12-23 15:02:29 -0800734 }
735
736 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800737 * Returns the user configuration of WFC preference setting
Malcolm Chen212ca652017-09-28 17:28:45 -0700738 * @deprecated. Use {@link #getWfcMode(boolean roaming)} instead.
Brad Ebinger16417b42017-03-07 13:48:50 -0800739 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700740 public int getWfcMode() {
Malcolm Chen212ca652017-09-28 17:28:45 -0700741 return getWfcMode(false);
Brad Ebinger16417b42017-03-07 13:48:50 -0800742 }
743
744 /**
745 * Change persistent WFC preference setting.
746 *
Brad Ebinger479f52c2017-08-28 13:19:22 -0700747 * @deprecated Doesn't support MSIM devices. Use {@link #setWfcMode(int)} instead.
Etan Cohena00c9192014-12-23 15:02:29 -0800748 */
749 public static void setWfcMode(Context context, int wfcMode) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700750 ImsManager mgr = ImsManager.getInstance(context,
751 SubscriptionManager.getDefaultVoicePhoneId());
752 if (mgr != null) {
753 mgr.setWfcMode(wfcMode);
754 }
755 loge("setWfcMode: ImsManager null, can not set value.");
Pavel Zhamaitsiak9e6eca22015-03-16 15:30:53 -0700756 }
757
Meng Wang37477012016-09-20 09:59:56 -0700758 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800759 * Change persistent WFC preference setting for slot.
760 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700761 public void setWfcMode(int wfcMode) {
762 if (DBG) log("setWfcMode(i) - setting=" + wfcMode);
Malcolm Chen212ca652017-09-28 17:28:45 -0700763
764 SubscriptionManager.setSubscriptionProperty(getSubId(),
765 SubscriptionManager.WFC_IMS_MODE, Integer.toString(wfcMode));
Brad Ebinger16417b42017-03-07 13:48:50 -0800766
Brad Ebinger479f52c2017-08-28 13:19:22 -0700767 setWfcModeInternal(wfcMode);
Brad Ebinger16417b42017-03-07 13:48:50 -0800768 }
769
770 /**
Suresh Koleti76491082017-04-21 18:39:50 +0530771 * Changes the WFC mode to its default value for Carriers with non-editable WFC settings.
772 */
773 private void updateDefaultWfcMode() {
774 if (DBG) log("updateDefaultWfcMode");
Brad Ebinger479f52c2017-08-28 13:19:22 -0700775 if (!getBooleanCarrierConfig(CarrierConfigManager.KEY_EDITABLE_WFC_MODE_BOOL)) {
776 setWfcMode(getIntCarrierConfig(
Suresh Koleti76491082017-04-21 18:39:50 +0530777 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_MODE_INT));
778 }
779 }
780
781 /**
Meng Wang37477012016-09-20 09:59:56 -0700782 * Returns the user configuration of WFC preference setting
783 *
784 * @param roaming {@code false} for home network setting, {@code true} for roaming setting
Brad Ebinger16417b42017-03-07 13:48:50 -0800785 *
Brad Ebinger479f52c2017-08-28 13:19:22 -0700786 * @deprecated Doesn't support MSIM devices. Use {@link #getWfcMode(boolean)} instead.
Meng Wang37477012016-09-20 09:59:56 -0700787 */
788 public static int getWfcMode(Context context, boolean roaming) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700789 ImsManager mgr = ImsManager.getInstance(context,
790 SubscriptionManager.getDefaultVoicePhoneId());
791 if (mgr != null) {
792 return mgr.getWfcMode(roaming);
Meng Wang37477012016-09-20 09:59:56 -0700793 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700794 loge("getWfcMode: ImsManager null, returning default value.");
795 return ImsConfig.WfcModeFeatureValueConstants.WIFI_ONLY;
Meng Wang37477012016-09-20 09:59:56 -0700796 }
797
798 /**
Malcolm Chen212ca652017-09-28 17:28:45 -0700799 * Returns the user configuration of WFC preference setting for slot. If not set, it
800 * queries CarrierConfig value as default.
Brad Ebinger16417b42017-03-07 13:48:50 -0800801 *
802 * @param roaming {@code false} for home network setting, {@code true} for roaming setting
803 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700804 public int getWfcMode(boolean roaming) {
Brad Ebinger16417b42017-03-07 13:48:50 -0800805 int setting = 0;
806 if (!roaming) {
Malcolm Chen212ca652017-09-28 17:28:45 -0700807 setting = SubscriptionManager.getIntegerSubscriptionProperty(
808 getSubId(), SubscriptionManager.WFC_IMS_MODE,
809 SUB_PROPERTY_NOT_INITIALIZED, mContext);
810
811 // SUB_PROPERTY_NOT_INITIALIZED indicates it's never set in sub db.
812 if (setting == SUB_PROPERTY_NOT_INITIALIZED) {
813 setting = getIntCarrierConfig(
814 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_MODE_INT);
815 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700816 if (DBG) log("getWfcMode - setting=" + setting);
Brad Ebinger16417b42017-03-07 13:48:50 -0800817 } else {
Malcolm Chen212ca652017-09-28 17:28:45 -0700818 setting = SubscriptionManager.getIntegerSubscriptionProperty(
819 getSubId(), SubscriptionManager.WFC_IMS_ROAMING_MODE,
820 SUB_PROPERTY_NOT_INITIALIZED, mContext);
821
822 // SUB_PROPERTY_NOT_INITIALIZED indicates it's never set in sub db.
823 if (setting == SUB_PROPERTY_NOT_INITIALIZED) {
824 setting = getIntCarrierConfig(
825 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_MODE_INT);
826 }
827
Brad Ebinger479f52c2017-08-28 13:19:22 -0700828 if (DBG) log("getWfcMode (roaming) - setting=" + setting);
Brad Ebinger16417b42017-03-07 13:48:50 -0800829 }
830 return setting;
831 }
832
833 /**
Meng Wang37477012016-09-20 09:59:56 -0700834 * Change persistent WFC preference setting
835 *
836 * @param roaming {@code false} for home network setting, {@code true} for roaming setting
Brad Ebinger16417b42017-03-07 13:48:50 -0800837 *
Brad Ebinger479f52c2017-08-28 13:19:22 -0700838 * @deprecated Doesn't support MSIM devices. Please use {@link #setWfcMode(int, boolean)}
839 * instead.
Meng Wang37477012016-09-20 09:59:56 -0700840 */
841 public static void setWfcMode(Context context, int wfcMode, boolean roaming) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700842 ImsManager mgr = ImsManager.getInstance(context,
843 SubscriptionManager.getDefaultVoicePhoneId());
844 if (mgr != null) {
845 mgr.setWfcMode(wfcMode, roaming);
Meng Wang37477012016-09-20 09:59:56 -0700846 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700847 loge("setWfcMode: ImsManager null, can not set value.");
Meng Wang37477012016-09-20 09:59:56 -0700848 }
849
Brad Ebinger16417b42017-03-07 13:48:50 -0800850 /**
851 * Change persistent WFC preference setting
852 *
853 * @param roaming {@code false} for home network setting, {@code true} for roaming setting
854 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700855 public void setWfcMode(int wfcMode, boolean roaming) {
Brad Ebinger16417b42017-03-07 13:48:50 -0800856 if (!roaming) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700857 if (DBG) log("setWfcMode(i,b) - setting=" + wfcMode);
Malcolm Chen212ca652017-09-28 17:28:45 -0700858 SubscriptionManager.setSubscriptionProperty(getSubId(),
859 SubscriptionManager.WFC_IMS_MODE, Integer.toString(wfcMode));
Brad Ebinger16417b42017-03-07 13:48:50 -0800860 } else {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700861 if (DBG) log("setWfcMode(i,b) (roaming) - setting=" + wfcMode);
Malcolm Chen212ca652017-09-28 17:28:45 -0700862 SubscriptionManager.setSubscriptionProperty(getSubId(),
863 SubscriptionManager.WFC_IMS_ROAMING_MODE, Integer.toString(wfcMode));
Brad Ebinger16417b42017-03-07 13:48:50 -0800864 }
865
Brad Ebinger479f52c2017-08-28 13:19:22 -0700866 TelephonyManager tm = (TelephonyManager)
867 mContext.getSystemService(Context.TELEPHONY_SERVICE);
868 if (roaming == tm.isNetworkRoaming(getSubId())) {
869 setWfcModeInternal(wfcMode);
870 }
871 }
872
873 private int getSubId() {
Brad Ebinger16417b42017-03-07 13:48:50 -0800874 int[] subIds = SubscriptionManager.getSubId(mPhoneId);
875 int subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
876 if (subIds != null && subIds.length >= 1) {
877 subId = subIds[0];
878 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700879 return subId;
Brad Ebinger16417b42017-03-07 13:48:50 -0800880 }
881
Pavel Zhamaitsiak9e6eca22015-03-16 15:30:53 -0700882 private static void setWfcModeInternal(Context context, int wfcMode) {
Etan Cohena00c9192014-12-23 15:02:29 -0800883 final ImsManager imsManager = ImsManager.getInstance(context,
884 SubscriptionManager.getDefaultVoicePhoneId());
885 if (imsManager != null) {
886 final int value = wfcMode;
Pavel Zhamaitsiak47aeacf2016-03-30 18:54:55 -0700887 Thread thread = new Thread(new Runnable() {
Etan Cohena00c9192014-12-23 15:02:29 -0800888 public void run() {
889 try {
Brad Ebinger172977a2018-01-16 09:36:56 -0800890 imsManager.getConfigInterface().setConfig(
Etan Cohena00c9192014-12-23 15:02:29 -0800891 ImsConfig.ConfigConstants.VOICE_OVER_WIFI_MODE,
892 value);
893 } catch (ImsException e) {
894 // do nothing
895 }
896 }
897 });
Pavel Zhamaitsiak47aeacf2016-03-30 18:54:55 -0700898 thread.start();
Etan Cohena00c9192014-12-23 15:02:29 -0800899 }
900 }
901
Brad Ebinger479f52c2017-08-28 13:19:22 -0700902 private void setWfcModeInternal(int wfcMode) {
Brad Ebinger16417b42017-03-07 13:48:50 -0800903 final int value = wfcMode;
904 Thread thread = new Thread(() -> {
Malcolm Chen212ca652017-09-28 17:28:45 -0700905 try {
Brad Ebinger172977a2018-01-16 09:36:56 -0800906 getConfigInterface().setConfig(
Malcolm Chen212ca652017-09-28 17:28:45 -0700907 ImsConfig.ConfigConstants.VOICE_OVER_WIFI_MODE, value);
908 } catch (ImsException e) {
909 // do nothing
910 }
Brad Ebinger16417b42017-03-07 13:48:50 -0800911 });
912 thread.start();
913 }
914
Etan Cohena00c9192014-12-23 15:02:29 -0800915 /**
916 * Returns the user configuration of WFC roaming setting
Brad Ebinger16417b42017-03-07 13:48:50 -0800917 *
918 * @deprecated Does not support MSIM devices. Please use
Brad Ebinger479f52c2017-08-28 13:19:22 -0700919 * {@link #isWfcRoamingEnabledByUser()} instead.
Etan Cohena00c9192014-12-23 15:02:29 -0800920 */
921 public static boolean isWfcRoamingEnabledByUser(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700922 ImsManager mgr = ImsManager.getInstance(context,
923 SubscriptionManager.getDefaultVoicePhoneId());
924 if (mgr != null) {
925 return mgr.isWfcRoamingEnabledByUser();
926 }
927 loge("isWfcRoamingEnabledByUser: ImsManager null, returning default value.");
928 return false;
Etan Cohena00c9192014-12-23 15:02:29 -0800929 }
930
931 /**
Malcolm Chen212ca652017-09-28 17:28:45 -0700932 * Returns the user configuration of WFC roaming setting for slot. If not set, it
933 * queries CarrierConfig value as default.
Brad Ebinger16417b42017-03-07 13:48:50 -0800934 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700935 public boolean isWfcRoamingEnabledByUser() {
Malcolm Chen212ca652017-09-28 17:28:45 -0700936 int setting = SubscriptionManager.getIntegerSubscriptionProperty(
937 getSubId(), SubscriptionManager.WFC_IMS_ROAMING_ENABLED,
938 SUB_PROPERTY_NOT_INITIALIZED, mContext);
939 if (setting == SUB_PROPERTY_NOT_INITIALIZED) {
940 return getBooleanCarrierConfig(
941 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_ENABLED_BOOL);
942 } else {
manabu, shimoda96aee542017-10-06 15:39:36 +0900943 return setting == ImsConfig.FeatureValueConstants.ON;
Malcolm Chen212ca652017-09-28 17:28:45 -0700944 }
Brad Ebinger16417b42017-03-07 13:48:50 -0800945 }
946
947 /**
Etan Cohena00c9192014-12-23 15:02:29 -0800948 * Change persistent WFC roaming enabled setting
949 */
950 public static void setWfcRoamingSetting(Context context, boolean enabled) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700951 ImsManager mgr = ImsManager.getInstance(context,
Etan Cohena00c9192014-12-23 15:02:29 -0800952 SubscriptionManager.getDefaultVoicePhoneId());
Brad Ebinger479f52c2017-08-28 13:19:22 -0700953 if (mgr != null) {
954 mgr.setWfcRoamingSetting(enabled);
Etan Cohena00c9192014-12-23 15:02:29 -0800955 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700956 loge("setWfcRoamingSetting: ImsManager null, value not set.");
Etan Cohena00c9192014-12-23 15:02:29 -0800957 }
958
959 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800960 * Change persistent WFC roaming enabled setting
961 */
Brad Ebinger479f52c2017-08-28 13:19:22 -0700962 public void setWfcRoamingSetting(boolean enabled) {
Malcolm Chen212ca652017-09-28 17:28:45 -0700963 SubscriptionManager.setSubscriptionProperty(getSubId(),
964 SubscriptionManager.WFC_IMS_ROAMING_ENABLED, booleanToPropertyString(enabled)
965 );
Brad Ebinger16417b42017-03-07 13:48:50 -0800966
967 setWfcRoamingSettingInternal(enabled);
968 }
969
970 private void setWfcRoamingSettingInternal(boolean enabled) {
971 final int value = enabled
972 ? ImsConfig.FeatureValueConstants.ON
973 : ImsConfig.FeatureValueConstants.OFF;
974 Thread thread = new Thread(() -> {
Malcolm Chen212ca652017-09-28 17:28:45 -0700975 try {
Brad Ebinger172977a2018-01-16 09:36:56 -0800976 getConfigInterface().setConfig(
Malcolm Chen212ca652017-09-28 17:28:45 -0700977 ImsConfig.ConfigConstants.VOICE_OVER_WIFI_ROAMING, value);
978 } catch (ImsException e) {
979 // do nothing
980 }
Brad Ebinger16417b42017-03-07 13:48:50 -0800981 });
982 thread.start();
983 }
984
985 /**
Etan Cohena00c9192014-12-23 15:02:29 -0800986 * Returns a platform configuration for WFC which may override the user
987 * setting. Note: WFC presumes that VoLTE is enabled (these are
988 * configuration settings which must be done correctly).
Brad Ebinger16417b42017-03-07 13:48:50 -0800989 *
Brad Ebinger479f52c2017-08-28 13:19:22 -0700990 * @deprecated Doesn't work for MSIM devices. Use {@link #isWfcEnabledByPlatform()}
Brad Ebinger16417b42017-03-07 13:48:50 -0800991 * instead.
Etan Cohena00c9192014-12-23 15:02:29 -0800992 */
993 public static boolean isWfcEnabledByPlatform(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -0700994 ImsManager mgr = ImsManager.getInstance(context,
995 SubscriptionManager.getDefaultVoicePhoneId());
996 if (mgr != null) {
997 return mgr.isWfcEnabledByPlatform();
Etan Cohena00c9192014-12-23 15:02:29 -0800998 }
Brad Ebinger479f52c2017-08-28 13:19:22 -0700999 loge("isWfcEnabledByPlatform: ImsManager null, returning default value.");
1000 return false;
Pavel Zhamaitsiak57911d12015-10-20 14:26:34 -07001001 }
1002
1003 /**
Brad Ebinger16417b42017-03-07 13:48:50 -08001004 * Returns a platform configuration for WFC which may override the user
1005 * setting per slot. Note: WFC presumes that VoLTE is enabled (these are
1006 * configuration settings which must be done correctly).
1007 */
Brad Ebinger479f52c2017-08-28 13:19:22 -07001008 public boolean isWfcEnabledByPlatform() {
Malcolm Chen18837ff2017-10-25 17:05:41 -07001009 // We first read the per slot value. If doesn't exist, we read the general value. If still
1010 // doesn't exist, we use the hardcoded default value.
1011 if (SystemProperties.getInt(PROPERTY_DBG_WFC_AVAIL_OVERRIDE +
1012 Integer.toString(mPhoneId), SYSTEM_PROPERTY_NOT_SET) == 1 ||
1013 SystemProperties.getInt(
1014 PROPERTY_DBG_WFC_AVAIL_OVERRIDE, SYSTEM_PROPERTY_NOT_SET) == 1) {
Brad Ebinger16417b42017-03-07 13:48:50 -08001015 return true;
1016 }
1017
1018 return mContext.getResources().getBoolean(
1019 com.android.internal.R.bool.config_device_wfc_ims_available) &&
Brad Ebinger479f52c2017-08-28 13:19:22 -07001020 getBooleanCarrierConfig(
Brad Ebinger16417b42017-03-07 13:48:50 -08001021 CarrierConfigManager.KEY_CARRIER_WFC_IMS_AVAILABLE_BOOL) &&
Brad Ebinger479f52c2017-08-28 13:19:22 -07001022 isGbaValid();
Etan Cohena00c9192014-12-23 15:02:29 -08001023 }
1024
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001025 /**
Brad Ebinger16417b42017-03-07 13:48:50 -08001026 * If carrier requires that IMS is only available if GBA capable SIM is used,
1027 * then this function checks GBA bit in EF IST.
1028 *
1029 * Format of EF IST is defined in 3GPP TS 31.103 (Section 4.2.7).
1030 */
Brad Ebinger479f52c2017-08-28 13:19:22 -07001031 private boolean isGbaValid() {
1032 if (getBooleanCarrierConfig(
Brad Ebinger16417b42017-03-07 13:48:50 -08001033 CarrierConfigManager.KEY_CARRIER_IMS_GBA_REQUIRED_BOOL)) {
Brad Ebinger479f52c2017-08-28 13:19:22 -07001034 final TelephonyManager telephonyManager = new TelephonyManager(mContext, getSubId());
Brad Ebinger16417b42017-03-07 13:48:50 -08001035 String efIst = telephonyManager.getIsimIst();
1036 if (efIst == null) {
Brad Ebinger479f52c2017-08-28 13:19:22 -07001037 loge("isGbaValid - ISF is NULL");
Brad Ebinger16417b42017-03-07 13:48:50 -08001038 return true;
1039 }
1040 boolean result = efIst != null && efIst.length() > 1 &&
1041 (0x02 & (byte)efIst.charAt(1)) != 0;
Brad Ebinger479f52c2017-08-28 13:19:22 -07001042 if (DBG) log("isGbaValid - GBA capable=" + result + ", ISF=" + efIst);
Brad Ebinger16417b42017-03-07 13:48:50 -08001043 return result;
1044 }
1045 return true;
1046 }
1047
1048 /**
Malcolm Chen18837ff2017-10-25 17:05:41 -07001049 * Will return with config value or throw an ImsException if we receive an error from
1050 * ImsConfig for that value.
1051 */
1052 private boolean getProvisionedBool(ImsConfig config, int item) throws ImsException {
1053 int value = config.getProvisionedValue(item);
1054 if (value == ImsConfig.OperationStatusConstants.UNKNOWN) {
1055 throw new ImsException("getProvisionedBool failed with error for item: " + item,
1056 ImsReasonInfo.CODE_LOCAL_INTERNAL_ERROR);
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -07001057 }
Malcolm Chen18837ff2017-10-25 17:05:41 -07001058 return config.getProvisionedValue(item) == ImsConfig.FeatureValueConstants.ON;
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -07001059 }
1060
1061 /**
Malcolm Chen18837ff2017-10-25 17:05:41 -07001062 * Will return with config value or return false if we receive an error from
1063 * ImsConfig for that value.
Brad Ebingerbe6cb672017-08-25 14:55:00 -07001064 */
Malcolm Chen18837ff2017-10-25 17:05:41 -07001065 private boolean getProvisionedBoolNoException(int item) {
1066 try {
1067 ImsConfig config = getConfigInterface();
1068 return getProvisionedBool(config, item);
1069 } catch (ImsException ex) {
1070 return false;
Brad Ebingerbe6cb672017-08-25 14:55:00 -07001071 }
1072 }
1073
1074 /**
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001075 * Sync carrier config and user settings with ImsConfig.
1076 *
1077 * @param context for the manager object
1078 * @param phoneId phone id
1079 * @param force update
Brad Ebinger16417b42017-03-07 13:48:50 -08001080 *
Brad Ebinger479f52c2017-08-28 13:19:22 -07001081 * @deprecated Doesn't support MSIM devices. Use {@link #updateImsServiceConfig(boolean)}
1082 * instead.
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001083 */
1084 public static void updateImsServiceConfig(Context context, int phoneId, boolean force) {
Brad Ebinger479f52c2017-08-28 13:19:22 -07001085 ImsManager mgr = ImsManager.getInstance(context, phoneId);
1086 if (mgr != null) {
1087 mgr.updateImsServiceConfig(force);
Pavel Zhamaitsiakfc202992016-03-29 18:07:38 -07001088 }
Brad Ebinger479f52c2017-08-28 13:19:22 -07001089 loge("updateImsServiceConfig: ImsManager null, returning without update.");
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001090 }
1091
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -07001092 /**
Brad Ebinger16417b42017-03-07 13:48:50 -08001093 * Sync carrier config and user settings with ImsConfig.
1094 *
Brad Ebinger16417b42017-03-07 13:48:50 -08001095 * @param force update
1096 */
Brad Ebinger479f52c2017-08-28 13:19:22 -07001097 public void updateImsServiceConfig(boolean force) {
Brad Ebinger16417b42017-03-07 13:48:50 -08001098 if (!force) {
Brad Ebinger479f52c2017-08-28 13:19:22 -07001099 TelephonyManager tm = new TelephonyManager(mContext, getSubId());
1100 if (tm.getSimState() != TelephonyManager.SIM_STATE_READY) {
1101 log("updateImsServiceConfig: SIM not ready");
Brad Ebinger16417b42017-03-07 13:48:50 -08001102 // Don't disable IMS if SIM is not ready
1103 return;
1104 }
1105 }
1106
1107 if (!mConfigUpdated || force) {
1108 try {
Brad Ebinger16417b42017-03-07 13:48:50 -08001109 // TODO: Extend ImsConfig API and set all feature values in single function call.
1110
1111 // Note: currently the order of updates is set to produce different order of
Brad Ebinger172977a2018-01-16 09:36:56 -08001112 // changeEnabledCapabilities() function calls from setAdvanced4GMode(). This is done
1113 // to differentiate this code path from vendor code perspective.
Brad Ebinger16417b42017-03-07 13:48:50 -08001114 boolean isImsUsed = updateVolteFeatureValue();
1115 isImsUsed |= updateWfcFeatureAndProvisionedValues();
1116 isImsUsed |= updateVideoCallFeatureValue();
1117
Brad Ebinger479f52c2017-08-28 13:19:22 -07001118 if (isImsUsed || !isTurnOffImsAllowedByPlatform()) {
Brad Ebinger16417b42017-03-07 13:48:50 -08001119 // Turn on IMS if it is used.
1120 // Also, if turning off is not allowed for current carrier,
1121 // we need to turn IMS on because it might be turned off before
1122 // phone switched to current carrier.
Brad Ebinger479f52c2017-08-28 13:19:22 -07001123 log("updateImsServiceConfig: turnOnIms");
Brad Ebinger16417b42017-03-07 13:48:50 -08001124 turnOnIms();
1125 } else {
1126 // Turn off IMS if it is not used AND turning off is allowed for carrier.
Brad Ebinger479f52c2017-08-28 13:19:22 -07001127 log("updateImsServiceConfig: turnOffIms");
Brad Ebinger16417b42017-03-07 13:48:50 -08001128 turnOffIms();
1129 }
1130
1131 mConfigUpdated = true;
Brad Ebinger172977a2018-01-16 09:36:56 -08001132 } catch (ImsException | RemoteException e) {
Brad Ebinger479f52c2017-08-28 13:19:22 -07001133 loge("updateImsServiceConfig: ", e);
Brad Ebinger16417b42017-03-07 13:48:50 -08001134 mConfigUpdated = false;
1135 }
1136 }
1137 }
1138
1139 /**
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -07001140 * Update VoLTE config
1141 * @return whether feature is On
1142 * @throws ImsException
1143 */
Brad Ebinger172977a2018-01-16 09:36:56 -08001144 private boolean updateVolteFeatureValue() throws RemoteException {
Brad Ebinger479f52c2017-08-28 13:19:22 -07001145 boolean available = isVolteEnabledByPlatform();
1146 boolean enabled = isEnhanced4gLteModeSettingEnabledByUser();
1147 boolean isNonTty = isNonTtyOrTtyOnVolteEnabled();
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -08001148 boolean isFeatureOn = available && enabled && isNonTty;
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001149
1150 log("updateVolteFeatureValue: available = " + available
1151 + ", enabled = " + enabled
1152 + ", nonTTY = " + isNonTty);
1153
Brad Ebinger172977a2018-01-16 09:36:56 -08001154 changeMmTelCapability(MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE,
1155 ImsRegistrationImplBase.REGISTRATION_TECH_LTE, isFeatureOn);
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -07001156
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -08001157 return isFeatureOn;
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001158 }
1159
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -07001160 /**
Jack Yu643ffe42016-07-08 14:25:46 -07001161 * Update video call over LTE config
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -07001162 * @return whether feature is On
1163 * @throws ImsException
1164 */
Brad Ebinger172977a2018-01-16 09:36:56 -08001165 private boolean updateVideoCallFeatureValue() throws RemoteException {
Brad Ebinger479f52c2017-08-28 13:19:22 -07001166 boolean available = isVtEnabledByPlatform();
1167 boolean enabled = isVtEnabledByUser();
1168 boolean isNonTty = isNonTtyOrTtyOnVolteEnabled();
Amit Mahajan24f7b162016-07-21 16:33:53 -07001169 boolean isDataEnabled = isDataEnabled();
Brad Ebinger479f52c2017-08-28 13:19:22 -07001170 boolean ignoreDataEnabledChanged = getBooleanCarrierConfig(
Jack Yu57781852016-11-16 17:20:38 -08001171 CarrierConfigManager.KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS);
Jack Yu643ffe42016-07-08 14:25:46 -07001172
Jack Yu57781852016-11-16 17:20:38 -08001173 boolean isFeatureOn = available && enabled && isNonTty
1174 && (ignoreDataEnabledChanged || isDataEnabled);
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001175
1176 log("updateVideoCallFeatureValue: available = " + available
1177 + ", enabled = " + enabled
Jack Yu643ffe42016-07-08 14:25:46 -07001178 + ", nonTTY = " + isNonTty
Amit Mahajan24f7b162016-07-21 16:33:53 -07001179 + ", data enabled = " + isDataEnabled);
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001180
Brad Ebinger172977a2018-01-16 09:36:56 -08001181 changeMmTelCapability(MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VIDEO,
1182 ImsRegistrationImplBase.REGISTRATION_TECH_LTE, isFeatureOn);
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -07001183
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -08001184 return isFeatureOn;
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001185 }
1186
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -07001187 /**
1188 * Update WFC config
1189 * @return whether feature is On
1190 * @throws ImsException
1191 */
Brad Ebinger172977a2018-01-16 09:36:56 -08001192 private boolean updateWfcFeatureAndProvisionedValues() throws RemoteException {
Brad Ebinger479f52c2017-08-28 13:19:22 -07001193 TelephonyManager tm = new TelephonyManager(mContext, getSubId());
1194 boolean isNetworkRoaming = tm.isNetworkRoaming();
1195 boolean available = isWfcEnabledByPlatform();
1196 boolean enabled = isWfcEnabledByUser();
Suresh Koleti76491082017-04-21 18:39:50 +05301197 updateDefaultWfcMode();
Brad Ebinger479f52c2017-08-28 13:19:22 -07001198 int mode = getWfcMode(isNetworkRoaming);
1199 boolean roaming = isWfcRoamingEnabledByUser();
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -08001200 boolean isFeatureOn = available && enabled;
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001201
1202 log("updateWfcFeatureAndProvisionedValues: available = " + available
1203 + ", enabled = " + enabled
1204 + ", mode = " + mode
1205 + ", roaming = " + roaming);
1206
Brad Ebinger172977a2018-01-16 09:36:56 -08001207 changeMmTelCapability(MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE,
1208 ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN, isFeatureOn);
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001209
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -08001210 if (!isFeatureOn) {
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001211 mode = ImsConfig.WfcModeFeatureValueConstants.CELLULAR_PREFERRED;
1212 roaming = false;
1213 }
1214 setWfcModeInternal(mContext, mode);
Brad Ebinger16417b42017-03-07 13:48:50 -08001215 setWfcRoamingSettingInternal(roaming);
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -07001216
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -08001217 return isFeatureOn;
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001218 }
1219
Brad Ebinger16780ff2017-01-26 11:18:21 -08001220 /**
Brad Ebinger479f52c2017-08-28 13:19:22 -07001221 * Do NOT use this directly, instead use {@link #getInstance(Context, int)}.
Brad Ebinger16780ff2017-01-26 11:18:21 -08001222 */
1223 @VisibleForTesting
1224 public ImsManager(Context context, int phoneId) {
Wink Savilleef36ef62014-06-11 08:39:38 -07001225 mContext = context;
Etan Cohenabbd7882014-09-26 22:35:35 -07001226 mPhoneId = phoneId;
Brad Ebinger16780ff2017-01-26 11:18:21 -08001227 mConfigDynamicBind = mContext.getResources().getBoolean(
1228 com.android.internal.R.bool.config_dynamic_bind_ims);
Brad Ebinger16417b42017-03-07 13:48:50 -08001229 mConfigManager = (CarrierConfigManager) context.getSystemService(
1230 Context.CARRIER_CONFIG_SERVICE);
Brad Ebinger16780ff2017-01-26 11:18:21 -08001231 createImsService();
1232 }
1233
1234 /**
Brad Ebinger16780ff2017-01-26 11:18:21 -08001235 * @return Whether or not ImsManager is configured to Dynamically bind or not to support legacy
1236 * devices.
1237 */
1238 public boolean isDynamicBinding() {
1239 return mConfigDynamicBind;
Wink Savilleef36ef62014-06-11 08:39:38 -07001240 }
1241
Etan Cohenf4311122015-02-26 17:47:13 -08001242 /*
Brad Ebingerff097922017-06-19 15:43:08 -07001243 * Returns a flag indicating whether the IMS service is available. If it is not available,
1244 * it will try to connect before reporting failure.
Etan Cohenf4311122015-02-26 17:47:13 -08001245 */
1246 public boolean isServiceAvailable() {
Brad Ebingerff097922017-06-19 15:43:08 -07001247 connectIfServiceIsAvailable();
Brad Ebinger16780ff2017-01-26 11:18:21 -08001248 // mImsServiceProxy will always create an ImsServiceProxy.
Brad Ebinger172977a2018-01-16 09:36:56 -08001249 return mMmTelFeatureConnection.isBinderAlive();
Etan Cohenf4311122015-02-26 17:47:13 -08001250 }
1251
Suresh Koleticc3139c2017-11-03 18:23:57 +05301252 /*
1253 * Returns a flag indicating whether the IMS service is ready to send requests to lower layers.
1254 */
1255 public boolean isServiceReady() {
1256 connectIfServiceIsAvailable();
Brad Ebinger172977a2018-01-16 09:36:56 -08001257 return mMmTelFeatureConnection.isBinderReady();
Suresh Koleticc3139c2017-11-03 18:23:57 +05301258 }
1259
Brad Ebingerff097922017-06-19 15:43:08 -07001260 /**
1261 * If the service is available, try to reconnect.
1262 */
1263 public void connectIfServiceIsAvailable() {
Brad Ebinger172977a2018-01-16 09:36:56 -08001264 if (mMmTelFeatureConnection == null || !mMmTelFeatureConnection.isBinderAlive()) {
Brad Ebingerff097922017-06-19 15:43:08 -07001265 createImsService();
1266 }
1267 }
1268
Brad Ebinger172977a2018-01-16 09:36:56 -08001269 public void setConfigListener(ImsConfigListener listener) {
Pavel Zhamaitsiakf4b90322016-01-26 14:34:09 -08001270 mImsConfigListener = listener;
1271 }
1272
Brad Ebingerb10b61e2017-04-18 11:45:26 -07001273
1274 /**
1275 * Adds a callback for status changed events if the binder is already available. If it is not,
1276 * this method will throw an ImsException.
1277 */
Brad Ebinger172977a2018-01-16 09:36:56 -08001278 public void addNotifyStatusChangedCallbackIfAvailable(MmTelFeatureConnection.IFeatureUpdate c)
Brad Ebingerb10b61e2017-04-18 11:45:26 -07001279 throws ImsException {
Brad Ebinger172977a2018-01-16 09:36:56 -08001280 if (!mMmTelFeatureConnection.isBinderAlive()) {
Brad Ebingerb10b61e2017-04-18 11:45:26 -07001281 throw new ImsException("Binder is not active!",
1282 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1283 }
Brad Ebinger16780ff2017-01-26 11:18:21 -08001284 if (c != null) {
1285 mStatusCallbacks.add(c);
1286 }
1287 }
1288
Brad Ebinger172977a2018-01-16 09:36:56 -08001289 public void removeNotifyStatusChangedCallback(MmTelFeatureConnection.IFeatureUpdate c) {
Brad Ebinger44fd8af2017-12-14 14:24:02 -08001290 if (c != null) {
1291 mStatusCallbacks.remove(c);
1292 } else {
1293 Log.w(TAG, "removeNotifyStatusChangedCallback: callback is null!");
1294 }
1295 }
1296
Wink Savilleef36ef62014-06-11 08:39:38 -07001297 /**
1298 * Opens the IMS service for making calls and/or receiving generic IMS calls.
Brad Ebinger172977a2018-01-16 09:36:56 -08001299 * The caller may make subsequent calls through {@link #makeCall}.
Wink Savilleef36ef62014-06-11 08:39:38 -07001300 * The IMS service will register the device to the operator's network with the credentials
1301 * (from ISIM) periodically in order to receive calls from the operator's network.
Brad Ebinger172977a2018-01-16 09:36:56 -08001302 * When the IMS service receives a new call, it will call
1303 * {@link MmTelFeature.Listener#onIncomingCall}
1304 * The listener contains a call ID extra {@link #getCallId} and it can be used to take a call.
1305 * @param listener A {@link MmTelFeature.Listener}, which is the interface the
1306 * {@link MmTelFeature} uses to notify the framework of updates
1307 * @throws NullPointerException if {@code listener} is null
Wink Savilleef36ef62014-06-11 08:39:38 -07001308 * @throws ImsException if calling the IMS service results in an error
1309 * @see #getCallId
Wink Savilleef36ef62014-06-11 08:39:38 -07001310 */
Brad Ebinger172977a2018-01-16 09:36:56 -08001311 public void open(MmTelFeature.Listener listener) throws ImsException {
Wink Savilleef36ef62014-06-11 08:39:38 -07001312 checkAndThrowExceptionIfServiceUnavailable();
1313
Wink Savilleef36ef62014-06-11 08:39:38 -07001314 if (listener == null) {
1315 throw new NullPointerException("listener can't be null");
1316 }
1317
Wink Savilleef36ef62014-06-11 08:39:38 -07001318 try {
Brad Ebinger172977a2018-01-16 09:36:56 -08001319 mMmTelFeatureConnection.openConnection(listener);
Wink Savilleef36ef62014-06-11 08:39:38 -07001320 } catch (RemoteException e) {
Brad Ebinger172977a2018-01-16 09:36:56 -08001321 throw new ImsException("open()", e, ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
Wink Savilleef36ef62014-06-11 08:39:38 -07001322 }
Wink Savilleef36ef62014-06-11 08:39:38 -07001323 }
1324
1325 /**
Pavel Zhamaitsiakce410172016-04-15 10:55:56 -07001326 * Adds registration listener to the IMS service.
1327 *
1328 * @param serviceClass a service class specified in {@link ImsServiceClass}
1329 * For VoLTE service, it MUST be a {@link ImsServiceClass#MMTEL}.
1330 * @param listener To listen to IMS registration events; It cannot be null
1331 * @throws NullPointerException if {@code listener} is null
1332 * @throws ImsException if calling the IMS service results in an error
Brad Ebinger9a0280c2017-06-01 15:58:48 -07001333 *
1334 * @deprecated Use {@link #addRegistrationListener(ImsConnectionStateListener)} instead.
Pavel Zhamaitsiakce410172016-04-15 10:55:56 -07001335 */
1336 public void addRegistrationListener(int serviceClass, ImsConnectionStateListener listener)
1337 throws ImsException {
Brad Ebinger9a0280c2017-06-01 15:58:48 -07001338 addRegistrationListener(listener);
1339 }
1340
1341 /**
1342 * Adds registration listener to the IMS service.
1343 *
1344 * @param listener To listen to IMS registration events; It cannot be null
1345 * @throws NullPointerException if {@code listener} is null
1346 * @throws ImsException if calling the IMS service results in an error
Brad Ebinger172977a2018-01-16 09:36:56 -08001347 * @deprecated use {@link #addRegistrationCallback(ImsRegistrationImplBase.Callback)} and
1348 * {@link #addCapabilitiesCallback(ImsFeature.CapabilityCallback)} instead.
Brad Ebinger9a0280c2017-06-01 15:58:48 -07001349 */
Brad Ebinger44fd8af2017-12-14 14:24:02 -08001350 public void addRegistrationListener(ImsConnectionStateListener listener) throws ImsException {
Pavel Zhamaitsiakce410172016-04-15 10:55:56 -07001351 if (listener == null) {
1352 throw new NullPointerException("listener can't be null");
1353 }
Brad Ebinger172977a2018-01-16 09:36:56 -08001354 addRegistrationCallback(listener);
1355 // connect the ImsConnectionStateListener to the new CapabilityCallback.
1356 addCapabilitiesCallback(new ImsFeature.CapabilityCallback() {
1357 @Override
1358 public void onCapabilitiesStatusChanged(ImsFeature.Capabilities config) {
1359 listener.onFeatureCapabilityChangedAdapter(getRegistrationTech(), config);
Brad Ebinger9a0280c2017-06-01 15:58:48 -07001360 }
Brad Ebinger172977a2018-01-16 09:36:56 -08001361 });
1362 log("Registration Callback registered.");
1363 }
1364
1365 /**
1366 * Adds a callback that gets called when IMS registration has changed.
1367 * @param callback A {@link ImsRegistrationImplBase.Callback} that will notify the caller when
1368 * IMS registration status has changed.
1369 * @throws ImsException when the ImsService connection is not available.
1370 */
1371 public void addRegistrationCallback(ImsRegistrationImplBase.Callback callback)
1372 throws ImsException {
1373 if (callback == null) {
1374 throw new NullPointerException("registration callback can't be null");
Brad Ebinger9a0280c2017-06-01 15:58:48 -07001375 }
Brad Ebinger172977a2018-01-16 09:36:56 -08001376
1377 checkAndThrowExceptionIfServiceUnavailable();
1378 try {
1379 mMmTelFeatureConnection.addRegistrationCallback(callback);
1380 log("Registration Callback registered.");
1381 // Only record if there isn't a RemoteException.
1382 } catch (RemoteException e) {
1383 throw new ImsException("addRegistrationCallback(IRIB)", e,
1384 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1385 }
1386 }
1387
1388 /**
1389 * Adds a callback that gets called when MMTel capability status has changed, for example when
1390 * Voice over IMS or VT over IMS is not available currently.
1391 * @param callback A {@link ImsFeature.CapabilityCallback} that will notify the caller when
1392 * MMTel capability status has changed.
1393 * @throws ImsException when the ImsService connection is not available.
1394 */
1395 public void addCapabilitiesCallback(ImsFeature.CapabilityCallback callback)
1396 throws ImsException {
1397 if (callback == null) {
1398 throw new NullPointerException("capabilities callback can't be null");
1399 }
1400
1401 checkAndThrowExceptionIfServiceUnavailable();
1402 try {
1403 mMmTelFeatureConnection.addCapabilityCallback(callback);
1404 log("Capability Callback registered.");
1405 // Only record if there isn't a RemoteException.
1406 } catch (RemoteException e) {
1407 throw new ImsException("addCapabilitiesCallback(IF)", e,
1408 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
Pavel Zhamaitsiakce410172016-04-15 10:55:56 -07001409 }
1410 }
1411
1412 /**
Brad Ebinger16780ff2017-01-26 11:18:21 -08001413 * Removes the registration listener from the IMS service.
1414 *
Brad Ebinger16780ff2017-01-26 11:18:21 -08001415 * @param listener Previously registered listener that will be removed. Can not be null.
1416 * @throws NullPointerException if {@code listener} is null
1417 * @throws ImsException if calling the IMS service results in an error
1418 * instead.
1419 */
Brad Ebingerb5f30c72017-02-17 14:54:31 -08001420 public void removeRegistrationListener(ImsConnectionStateListener listener)
Brad Ebinger16780ff2017-01-26 11:18:21 -08001421 throws ImsException {
Brad Ebinger16780ff2017-01-26 11:18:21 -08001422 if (listener == null) {
1423 throw new NullPointerException("listener can't be null");
1424 }
1425
Brad Ebinger172977a2018-01-16 09:36:56 -08001426 checkAndThrowExceptionIfServiceUnavailable();
1427 try {
1428 mMmTelFeatureConnection.removeRegistrationCallback(listener);
1429 log("Registration Callback/Listener registered.");
1430 // Only record if there isn't a RemoteException.
1431 } catch (RemoteException e) {
1432 throw new ImsException("addRegistrationCallback()", e,
1433 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1434 }
1435 }
1436
1437 public @ImsRegistrationImplBase.ImsRegistrationTech int getRegistrationTech() {
1438 try {
1439 return mMmTelFeatureConnection.getRegistrationTech();
1440 } catch (RemoteException e) {
1441 Log.w(TAG, "getRegistrationTech: no connection to ImsService.");
1442 return ImsRegistrationImplBase.REGISTRATION_TECH_NONE;
Brad Ebinger16780ff2017-01-26 11:18:21 -08001443 }
1444 }
1445
1446 /**
Brad Ebinger172977a2018-01-16 09:36:56 -08001447 * Closes the connection and removes all active callbacks.
Wink Savilleef36ef62014-06-11 08:39:38 -07001448 * All the resources that were allocated to the service are also released.
Wink Savilleef36ef62014-06-11 08:39:38 -07001449 */
Brad Ebinger172977a2018-01-16 09:36:56 -08001450 public void close() {
1451 if (mMmTelFeatureConnection != null) {
1452 mMmTelFeatureConnection.closeConnection();
Wink Savilleef36ef62014-06-11 08:39:38 -07001453 }
Brad Ebinger172977a2018-01-16 09:36:56 -08001454 mUt = null;
1455 mConfig = null;
1456 mEcbm = null;
1457 mMultiEndpoint = null;
Wink Savilleef36ef62014-06-11 08:39:38 -07001458 }
1459
1460 /**
1461 * Gets the configuration interface to provision / withdraw the supplementary service settings.
1462 *
Wink Savilleef36ef62014-06-11 08:39:38 -07001463 * @return the Ut interface instance
1464 * @throws ImsException if getting the Ut interface results in an error
1465 */
Brad Ebinger172977a2018-01-16 09:36:56 -08001466 public ImsUtInterface getSupplementaryServiceConfiguration() throws ImsException {
Brad Ebinger16780ff2017-01-26 11:18:21 -08001467 // FIXME: manage the multiple Ut interfaces based on the session id
Brad Ebinger138b4a62017-06-20 16:29:50 -07001468 if (mUt != null && mUt.isBinderAlive()) {
1469 return mUt;
Wink Savilleef36ef62014-06-11 08:39:38 -07001470 }
1471
Brad Ebinger138b4a62017-06-20 16:29:50 -07001472 checkAndThrowExceptionIfServiceUnavailable();
1473 try {
Brad Ebinger172977a2018-01-16 09:36:56 -08001474 IImsUt iUt = mMmTelFeatureConnection.getUtInterface();
Brad Ebinger138b4a62017-06-20 16:29:50 -07001475
1476 if (iUt == null) {
1477 throw new ImsException("getSupplementaryServiceConfiguration()",
1478 ImsReasonInfo.CODE_UT_NOT_SUPPORTED);
1479 }
1480
1481 mUt = new ImsUt(iUt);
1482 } catch (RemoteException e) {
1483 throw new ImsException("getSupplementaryServiceConfiguration()", e,
1484 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1485 }
Wink Savilleef36ef62014-06-11 08:39:38 -07001486 return mUt;
1487 }
1488
1489 /**
Wink Savilleef36ef62014-06-11 08:39:38 -07001490 * Creates a {@link ImsCallProfile} from the service capabilities & IMS registration state.
1491 *
Wink Savilleef36ef62014-06-11 08:39:38 -07001492 * @param serviceType a service type that is specified in {@link ImsCallProfile}
1493 * {@link ImsCallProfile#SERVICE_TYPE_NONE}
1494 * {@link ImsCallProfile#SERVICE_TYPE_NORMAL}
1495 * {@link ImsCallProfile#SERVICE_TYPE_EMERGENCY}
1496 * @param callType a call type that is specified in {@link ImsCallProfile}
1497 * {@link ImsCallProfile#CALL_TYPE_VOICE}
1498 * {@link ImsCallProfile#CALL_TYPE_VT}
1499 * {@link ImsCallProfile#CALL_TYPE_VT_TX}
1500 * {@link ImsCallProfile#CALL_TYPE_VT_RX}
1501 * {@link ImsCallProfile#CALL_TYPE_VT_NODIR}
1502 * {@link ImsCallProfile#CALL_TYPE_VS}
1503 * {@link ImsCallProfile#CALL_TYPE_VS_TX}
1504 * {@link ImsCallProfile#CALL_TYPE_VS_RX}
1505 * @return a {@link ImsCallProfile} object
1506 * @throws ImsException if calling the IMS service results in an error
1507 */
Brad Ebinger172977a2018-01-16 09:36:56 -08001508 public ImsCallProfile createCallProfile(int serviceType, int callType) throws ImsException {
Wink Savilleef36ef62014-06-11 08:39:38 -07001509 checkAndThrowExceptionIfServiceUnavailable();
1510
1511 try {
Brad Ebinger172977a2018-01-16 09:36:56 -08001512 return mMmTelFeatureConnection.createCallProfile(serviceType, callType);
Wink Savilleef36ef62014-06-11 08:39:38 -07001513 } catch (RemoteException e) {
1514 throw new ImsException("createCallProfile()", e,
1515 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1516 }
1517 }
1518
1519 /**
1520 * Creates a {@link ImsCall} to make a call.
1521 *
Wink Savilleef36ef62014-06-11 08:39:38 -07001522 * @param profile a call profile to make the call
1523 * (it contains service type, call type, media information, etc.)
Brad Ebinger172977a2018-01-16 09:36:56 -08001524 * @param callees participants to invite the conference call
Wink Savilleef36ef62014-06-11 08:39:38 -07001525 * @param listener listen to the call events from {@link ImsCall}
1526 * @return a {@link ImsCall} object
1527 * @throws ImsException if calling the IMS service results in an error
1528 */
Brad Ebinger172977a2018-01-16 09:36:56 -08001529 public ImsCall makeCall(ImsCallProfile profile, String[] callees,
Wink Savilleef36ef62014-06-11 08:39:38 -07001530 ImsCall.Listener listener) throws ImsException {
1531 if (DBG) {
Brad Ebinger172977a2018-01-16 09:36:56 -08001532 log("makeCall :: profile=" + profile);
Wink Savilleef36ef62014-06-11 08:39:38 -07001533 }
1534
1535 checkAndThrowExceptionIfServiceUnavailable();
1536
1537 ImsCall call = new ImsCall(mContext, profile);
1538
1539 call.setListener(listener);
Brad Ebinger172977a2018-01-16 09:36:56 -08001540 ImsCallSession session = createCallSession(profile);
Wink Savilleef36ef62014-06-11 08:39:38 -07001541
1542 if ((callees != null) && (callees.length == 1)) {
1543 call.start(session, callees[0]);
1544 } else {
1545 call.start(session, callees);
1546 }
1547
1548 return call;
1549 }
1550
1551 /**
1552 * Creates a {@link ImsCall} to take an incoming call.
1553 *
Brad Ebinger16780ff2017-01-26 11:18:21 -08001554 * @param sessionId a session id which is obtained from {@link ImsManager#open}
Brad Ebinger172977a2018-01-16 09:36:56 -08001555 * @param incomingCallExtras the incoming call broadcast intent
Wink Savilleef36ef62014-06-11 08:39:38 -07001556 * @param listener to listen to the call events from {@link ImsCall}
1557 * @return a {@link ImsCall} object
1558 * @throws ImsException if calling the IMS service results in an error
1559 */
Brad Ebinger172977a2018-01-16 09:36:56 -08001560 public ImsCall takeCall(IImsCallSession session, Bundle incomingCallExtras,
Wink Savilleef36ef62014-06-11 08:39:38 -07001561 ImsCall.Listener listener) throws ImsException {
1562 if (DBG) {
Brad Ebinger172977a2018-01-16 09:36:56 -08001563 log("takeCall :: incomingCall=" + incomingCallExtras);
Wink Savilleef36ef62014-06-11 08:39:38 -07001564 }
1565
1566 checkAndThrowExceptionIfServiceUnavailable();
1567
Brad Ebinger172977a2018-01-16 09:36:56 -08001568 if (incomingCallExtras == null) {
Wink Savilleef36ef62014-06-11 08:39:38 -07001569 throw new ImsException("Can't retrieve session with null intent",
1570 ImsReasonInfo.CODE_LOCAL_ILLEGAL_ARGUMENT);
1571 }
1572
Brad Ebinger172977a2018-01-16 09:36:56 -08001573 String callId = getCallId(incomingCallExtras);
Wink Savilleef36ef62014-06-11 08:39:38 -07001574
1575 if (callId == null) {
1576 throw new ImsException("Call ID missing in the incoming call intent",
1577 ImsReasonInfo.CODE_LOCAL_ILLEGAL_ARGUMENT);
1578 }
1579
1580 try {
Wink Savilleef36ef62014-06-11 08:39:38 -07001581 if (session == null) {
1582 throw new ImsException("No pending session for the call",
1583 ImsReasonInfo.CODE_LOCAL_NO_PENDING_CALL);
1584 }
1585
1586 ImsCall call = new ImsCall(mContext, session.getCallProfile());
1587
1588 call.attachSession(new ImsCallSession(session));
1589 call.setListener(listener);
1590
1591 return call;
1592 } catch (Throwable t) {
1593 throw new ImsException("takeCall()", t, ImsReasonInfo.CODE_UNSPECIFIED);
1594 }
1595 }
1596
1597 /**
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -05001598 * Gets the config interface to get/set service/capability parameters.
1599 *
1600 * @return the ImsConfig instance.
1601 * @throws ImsException if getting the setting interface results in an error.
1602 */
1603 public ImsConfig getConfigInterface() throws ImsException {
Brad Ebinger138b4a62017-06-20 16:29:50 -07001604 if (mConfig != null && mConfig.isBinderAlive()) {
1605 return mConfig;
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -05001606 }
Brad Ebinger138b4a62017-06-20 16:29:50 -07001607
1608 checkAndThrowExceptionIfServiceUnavailable();
1609 try {
Brad Ebinger172977a2018-01-16 09:36:56 -08001610 IImsConfig config = mMmTelFeatureConnection.getConfigInterface();
Brad Ebinger138b4a62017-06-20 16:29:50 -07001611 if (config == null) {
1612 throw new ImsException("getConfigInterface()",
1613 ImsReasonInfo.CODE_LOCAL_SERVICE_UNAVAILABLE);
1614 }
1615 mConfig = new ImsConfig(config, mContext);
1616 } catch (RemoteException e) {
1617 throw new ImsException("getConfigInterface()", e,
1618 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1619 }
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -05001620 return mConfig;
1621 }
1622
Brad Ebinger172977a2018-01-16 09:36:56 -08001623 public void changeMmTelCapability(
1624 @MmTelFeature.MmTelCapabilities.MmTelCapability int capability,
1625 @ImsRegistrationImplBase.ImsRegistrationTech int radioTech,
1626 boolean isEnabled) throws RemoteException {
1627 CapabilityChangeRequest request = new CapabilityChangeRequest();
1628 if (isEnabled) {
1629 request.addCapabilitiesToEnableForTech(capability, radioTech);
1630 } else {
1631 request.addCapabilitiesToDisableForTech(capability, radioTech);
1632 }
1633 mMmTelFeatureConnection.changeEnabledCapabilities(request, null);
1634 if (mImsConfigListener != null) {
1635 mImsConfigListener.onSetFeatureResponse(capability,
1636 mMmTelFeatureConnection.getRegistrationTech(),
1637 isEnabled ? ImsConfig.FeatureValueConstants.ON
1638 : ImsConfig.FeatureValueConstants.OFF, -1);
1639 }
1640 }
1641
Hall Liub77d8972018-01-22 19:15:05 -08001642 public void setRttEnabled(boolean enabled) {
1643 try {
1644 setAdvanced4GMode(enabled || isEnhanced4gLteModeSettingEnabledByUser());
1645 final int value = enabled ? ImsConfig.FeatureValueConstants.ON :
1646 ImsConfig.FeatureValueConstants.OFF;
1647 Thread thread = new Thread(() -> {
1648 try {
1649 Log.i(ImsManager.class.getSimpleName(), "Setting RTT enabled to " + enabled);
1650 getConfigInterface().setProvisionedValue(
1651 ImsConfig.ConfigConstants.RTT_SETTING_ENABLED, value);
1652 } catch (ImsException e) {
1653 Log.e(ImsManager.class.getSimpleName(), "Unable to set RTT enabled to "
1654 + enabled + ": " + e);
1655 }
1656 });
1657 thread.start();
1658 } catch (ImsException e) {
1659 Log.e(ImsManager.class.getSimpleName(), "Unable to set RTT enabled to " + enabled
1660 + ": " + e);
1661 }
1662 }
1663
Hall Liue511a202017-08-17 15:49:58 -07001664 /**
1665 * Set the TTY mode. This is the actual tty mode (varies depending on peripheral status)
1666 */
1667 public void setTtyMode(int ttyMode) throws ImsException {
Brad Ebinger479f52c2017-08-28 13:19:22 -07001668 if (!getBooleanCarrierConfig(
Hall Liue511a202017-08-17 15:49:58 -07001669 CarrierConfigManager.KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL)) {
1670 setAdvanced4GMode((ttyMode == TelecomManager.TTY_MODE_OFF) &&
Brad Ebinger479f52c2017-08-28 13:19:22 -07001671 isEnhanced4gLteModeSettingEnabledByUser());
Hall Liue511a202017-08-17 15:49:58 -07001672 }
1673 }
1674
1675 /**
1676 * Sets the UI TTY mode. This is the preferred TTY mode that the user sets in the call
1677 * settings screen.
1678 */
Brad Ebingerb5f30c72017-02-17 14:54:31 -08001679 public void setUiTTYMode(Context context, int uiTtyMode, Message onComplete)
Shriram Ganeshc403b7b2014-08-14 14:18:57 +05301680 throws ImsException {
1681
Etan Cohen82f78122014-12-15 10:10:14 -08001682 checkAndThrowExceptionIfServiceUnavailable();
Shriram Ganeshc403b7b2014-08-14 14:18:57 +05301683
Etan Cohen82f78122014-12-15 10:10:14 -08001684 try {
Brad Ebinger172977a2018-01-16 09:36:56 -08001685 mMmTelFeatureConnection.setUiTTYMode(uiTtyMode, onComplete);
Etan Cohen82f78122014-12-15 10:10:14 -08001686 } catch (RemoteException e) {
1687 throw new ImsException("setTTYMode()", e,
1688 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1689 }
Shriram Ganeshc403b7b2014-08-14 14:18:57 +05301690 }
1691
Naveen Kalla525c3a22017-02-06 14:46:42 -08001692 private ImsReasonInfo makeACopy(ImsReasonInfo imsReasonInfo) {
1693 Parcel p = Parcel.obtain();
1694 imsReasonInfo.writeToParcel(p, 0);
1695 p.setDataPosition(0);
1696 ImsReasonInfo clonedReasonInfo = ImsReasonInfo.CREATOR.createFromParcel(p);
1697 p.recycle();
1698 return clonedReasonInfo;
1699 }
1700
1701 /**
1702 * Get Recent IMS Disconnect Reasons.
1703 *
1704 * @return ArrayList of ImsReasonInfo objects. MAX size of the arraylist
1705 * is MAX_RECENT_DISCONNECT_REASONS. The objects are in the
1706 * chronological order.
1707 */
1708 public ArrayList<ImsReasonInfo> getRecentImsDisconnectReasons() {
1709 ArrayList<ImsReasonInfo> disconnectReasons = new ArrayList<>();
1710
1711 for (ImsReasonInfo reason : mRecentDisconnectReasons) {
1712 disconnectReasons.add(makeACopy(reason));
1713 }
1714 return disconnectReasons;
1715 }
Brad Ebinger16417b42017-03-07 13:48:50 -08001716
Brad Ebinger172977a2018-01-16 09:36:56 -08001717 public int getImsServiceState() throws ImsException {
1718 return mMmTelFeatureConnection.getFeatureState();
Brad Ebinger16780ff2017-01-26 11:18:21 -08001719 }
Naveen Kalla525c3a22017-02-06 14:46:42 -08001720
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -05001721 /**
Junda Liue7663c02015-06-23 11:16:26 -07001722 * Get the boolean config from carrier config manager.
1723 *
Brad Ebinger16417b42017-03-07 13:48:50 -08001724 * @param key config key defined in CarrierConfigManager
1725 * @return boolean value of corresponding key.
1726 */
Brad Ebinger479f52c2017-08-28 13:19:22 -07001727 private boolean getBooleanCarrierConfig(String key) {
Brad Ebinger16417b42017-03-07 13:48:50 -08001728 int[] subIds = SubscriptionManager.getSubId(mPhoneId);
1729 int subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1730 if (subIds != null && subIds.length >= 1) {
1731 subId = subIds[0];
1732 }
1733 PersistableBundle b = null;
1734 if (mConfigManager != null) {
1735 // If an invalid subId is used, this bundle will contain default values.
1736 b = mConfigManager.getConfigForSubId(subId);
1737 }
1738 if (b != null) {
1739 return b.getBoolean(key);
1740 } else {
1741 // Return static default defined in CarrierConfigManager.
1742 return CarrierConfigManager.getDefaultConfig().getBoolean(key);
1743 }
1744 }
1745
1746 /**
fionaxu5803ef02016-03-08 11:48:48 -08001747 * Get the int config from carrier config manager.
1748 *
Brad Ebinger16417b42017-03-07 13:48:50 -08001749 * @param key config key defined in CarrierConfigManager
1750 * @return integer value of corresponding key.
1751 */
Brad Ebinger479f52c2017-08-28 13:19:22 -07001752 private int getIntCarrierConfig(String key) {
Brad Ebinger16417b42017-03-07 13:48:50 -08001753 int[] subIds = SubscriptionManager.getSubId(mPhoneId);
1754 int subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1755 if (subIds != null && subIds.length >= 1) {
1756 subId = subIds[0];
1757 }
1758 PersistableBundle b = null;
1759 if (mConfigManager != null) {
1760 // If an invalid subId is used, this bundle will contain default values.
1761 b = mConfigManager.getConfigForSubId(subId);
1762 }
1763 if (b != null) {
1764 return b.getInt(key);
1765 } else {
1766 // Return static default defined in CarrierConfigManager.
1767 return CarrierConfigManager.getDefaultConfig().getInt(key);
1768 }
1769 }
1770
1771 /**
Wink Savilleef36ef62014-06-11 08:39:38 -07001772 * Gets the call ID from the specified incoming call broadcast intent.
1773 *
Brad Ebinger172977a2018-01-16 09:36:56 -08001774 * @param incomingCallExtras the incoming call broadcast intent
Wink Savilleef36ef62014-06-11 08:39:38 -07001775 * @return the call ID or null if the intent does not contain it
1776 */
Brad Ebinger172977a2018-01-16 09:36:56 -08001777 private static String getCallId(Bundle incomingCallExtras) {
1778 if (incomingCallExtras == null) {
Wink Savilleef36ef62014-06-11 08:39:38 -07001779 return null;
1780 }
1781
Brad Ebinger172977a2018-01-16 09:36:56 -08001782 return incomingCallExtras.getString(EXTRA_CALL_ID);
Wink Savilleef36ef62014-06-11 08:39:38 -07001783 }
1784
1785 /**
Brad Ebingerb10b61e2017-04-18 11:45:26 -07001786 * Checks to see if the ImsService Binder is connected. If it is not, we try to create the
1787 * connection again.
Wink Savilleef36ef62014-06-11 08:39:38 -07001788 */
1789 private void checkAndThrowExceptionIfServiceUnavailable()
1790 throws ImsException {
Brad Ebinger172977a2018-01-16 09:36:56 -08001791 if (mMmTelFeatureConnection == null || !mMmTelFeatureConnection.isBinderAlive()) {
Brad Ebinger16780ff2017-01-26 11:18:21 -08001792 createImsService();
Wink Savilleef36ef62014-06-11 08:39:38 -07001793
Brad Ebinger172977a2018-01-16 09:36:56 -08001794 if (mMmTelFeatureConnection == null) {
Wink Savilleef36ef62014-06-11 08:39:38 -07001795 throw new ImsException("Service is unavailable",
1796 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1797 }
1798 }
1799 }
1800
Brad Ebinger16780ff2017-01-26 11:18:21 -08001801 /**
1802 * Binds the IMS service to make/receive the call. Supports two methods of exposing an
1803 * ImsService:
1804 * 1) com.android.ims.ImsService implementation in ServiceManager (deprecated).
1805 * 2) android.telephony.ims.ImsService implementation through ImsResolver.
1806 */
1807 private void createImsService() {
Brad Ebinger172977a2018-01-16 09:36:56 -08001808 Rlog.i(TAG, "Creating ImsService");
1809 mMmTelFeatureConnection = MmTelFeatureConnection.create(mContext, mPhoneId);
1810
Brad Ebinger44fd8af2017-12-14 14:24:02 -08001811 // Forwarding interface to tell mStatusCallbacks that the Proxy is unavailable.
Brad Ebinger172977a2018-01-16 09:36:56 -08001812 mMmTelFeatureConnection.setStatusCallback(new MmTelFeatureConnection.IFeatureUpdate() {
Brad Ebinger44fd8af2017-12-14 14:24:02 -08001813 @Override
1814 public void notifyStateChanged() {
Brad Ebinger172977a2018-01-16 09:36:56 -08001815 mStatusCallbacks.forEach(MmTelFeatureConnection.IFeatureUpdate::notifyStateChanged);
Brad Ebinger44fd8af2017-12-14 14:24:02 -08001816 }
1817
1818 @Override
1819 public void notifyUnavailable() {
Brad Ebinger172977a2018-01-16 09:36:56 -08001820 mStatusCallbacks.forEach(MmTelFeatureConnection.IFeatureUpdate::notifyUnavailable);
Brad Ebinger44fd8af2017-12-14 14:24:02 -08001821 }
1822 });
Etan Cohend7727462014-07-12 14:54:10 -07001823 }
1824
Wink Savilleef36ef62014-06-11 08:39:38 -07001825 /**
1826 * Creates a {@link ImsCallSession} with the specified call profile.
1827 * Use other methods, if applicable, instead of interacting with
1828 * {@link ImsCallSession} directly.
1829 *
Wink Savilleef36ef62014-06-11 08:39:38 -07001830 * @param profile a call profile to make the call
1831 */
Brad Ebinger172977a2018-01-16 09:36:56 -08001832 private ImsCallSession createCallSession(ImsCallProfile profile) throws ImsException {
Wink Savilleef36ef62014-06-11 08:39:38 -07001833 try {
Brad Ebingerb10b61e2017-04-18 11:45:26 -07001834 // Throws an exception if the ImsService Feature is not ready to accept commands.
Brad Ebinger172977a2018-01-16 09:36:56 -08001835 return new ImsCallSession(mMmTelFeatureConnection.createCallSession(profile));
Wink Savilleef36ef62014-06-11 08:39:38 -07001836 } catch (RemoteException e) {
Brad Ebingerb10b61e2017-04-18 11:45:26 -07001837 Rlog.w(TAG, "CreateCallSession: Error, remote exception: " + e.getMessage());
1838 throw new ImsException("createCallSession()", e,
1839 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1840
Wink Savilleef36ef62014-06-11 08:39:38 -07001841 }
1842 }
1843
Etan Cohena00c9192014-12-23 15:02:29 -08001844 private static void log(String s) {
Wink Savilleef36ef62014-06-11 08:39:38 -07001845 Rlog.d(TAG, s);
1846 }
1847
Etan Cohena00c9192014-12-23 15:02:29 -08001848 private static void loge(String s) {
Wink Savilleef36ef62014-06-11 08:39:38 -07001849 Rlog.e(TAG, s);
1850 }
1851
Etan Cohena00c9192014-12-23 15:02:29 -08001852 private static void loge(String s, Throwable t) {
Wink Savilleef36ef62014-06-11 08:39:38 -07001853 Rlog.e(TAG, s, t);
1854 }
1855
1856 /**
ram7da5a112014-07-16 20:59:27 +05301857 * Used for turning on IMS.if its off already
1858 */
Etan Cohen82f78122014-12-15 10:10:14 -08001859 private void turnOnIms() throws ImsException {
Brad Ebinger172977a2018-01-16 09:36:56 -08001860 TelephonyManager tm = (TelephonyManager)
1861 mContext.getSystemService(Context.TELEPHONY_SERVICE);
1862 tm.enableIms(mPhoneId);
ram7da5a112014-07-16 20:59:27 +05301863 }
1864
Omkar Kolangade75f3ca32014-10-24 11:10:52 -07001865 private boolean isImsTurnOffAllowed() {
Brad Ebinger479f52c2017-08-28 13:19:22 -07001866 return isTurnOffImsAllowedByPlatform()
1867 && (!isWfcEnabledByPlatform()
1868 || !isWfcEnabledByUser());
Omkar Kolangade75f3ca32014-10-24 11:10:52 -07001869 }
1870
Amit Mahajan9cba36d2016-08-11 10:17:23 -07001871 private void setLteFeatureValues(boolean turnOn) {
1872 log("setLteFeatureValues: " + turnOn);
Brad Ebinger172977a2018-01-16 09:36:56 -08001873 CapabilityChangeRequest request = new CapabilityChangeRequest();
1874 if (turnOn) {
1875 request.addCapabilitiesToEnableForTech(
1876 MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE,
1877 ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
1878 } else {
1879 request.addCapabilitiesToDisableForTech(
1880 MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE,
1881 ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
1882 }
Pavel Zhamaitsiakff29b9d2016-04-15 12:16:57 -07001883
Brad Ebinger172977a2018-01-16 09:36:56 -08001884 if (isVolteEnabledByPlatform()) {
1885 boolean ignoreDataEnabledChanged = getBooleanCarrierConfig(
1886 CarrierConfigManager.KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS);
1887 boolean enableViLte = turnOn && isVtEnabledByUser() &&
1888 (ignoreDataEnabledChanged || isDataEnabled());
1889 if (enableViLte) {
1890 request.addCapabilitiesToEnableForTech(
1891 MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VIDEO,
1892 ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
1893 } else {
1894 request.addCapabilitiesToDisableForTech(
1895 MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VIDEO,
1896 ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
Etan Cohenb651fa52014-10-22 10:51:29 -07001897 }
Brad Ebinger172977a2018-01-16 09:36:56 -08001898 }
1899 try {
1900 mMmTelFeatureConnection.changeEnabledCapabilities(request, null);
1901 } catch (RemoteException e) {
1902 Log.e(TAG, "setLteFeatureValues: Exception: " + e.getMessage());
Etan Cohencfc784d2014-08-07 18:40:31 -07001903 }
Amit Mahajan9cba36d2016-08-11 10:17:23 -07001904 }
1905
1906 private void setAdvanced4GMode(boolean turnOn) throws ImsException {
1907 checkAndThrowExceptionIfServiceUnavailable();
1908
1909 // if turnOn: first set feature values then call turnOnIms()
1910 // if turnOff: only set feature values if IMS turn off is not allowed. If turn off is
1911 // allowed, first call turnOffIms() then set feature values
Etan Cohencfc784d2014-08-07 18:40:31 -07001912 if (turnOn) {
Amit Mahajan9cba36d2016-08-11 10:17:23 -07001913 setLteFeatureValues(turnOn);
1914 log("setAdvanced4GMode: turnOnIms");
Etan Cohencfc784d2014-08-07 18:40:31 -07001915 turnOnIms();
Amit Mahajan9cba36d2016-08-11 10:17:23 -07001916 } else {
1917 if (isImsTurnOffAllowed()) {
1918 log("setAdvanced4GMode: turnOffIms");
1919 turnOffIms();
1920 }
1921 setLteFeatureValues(turnOn);
Etan Cohencfc784d2014-08-07 18:40:31 -07001922 }
1923 }
1924
ram7da5a112014-07-16 20:59:27 +05301925 /**
1926 * Used for turning off IMS completely in order to make the device CSFB'ed.
1927 * Once turned off, all calls will be over CS.
1928 */
Etan Cohen82f78122014-12-15 10:10:14 -08001929 private void turnOffIms() throws ImsException {
Brad Ebinger172977a2018-01-16 09:36:56 -08001930 TelephonyManager tm = (TelephonyManager)
1931 mContext.getSystemService(Context.TELEPHONY_SERVICE);
1932 tm.disableIms(mPhoneId);
ram7da5a112014-07-16 20:59:27 +05301933 }
1934
Naveen Kalla525c3a22017-02-06 14:46:42 -08001935 private void addToRecentDisconnectReasons(ImsReasonInfo reason) {
1936 if (reason == null) return;
1937 while (mRecentDisconnectReasons.size() >= MAX_RECENT_DISCONNECT_REASONS) {
1938 mRecentDisconnectReasons.removeFirst();
1939 }
1940 mRecentDisconnectReasons.addLast(reason);
1941 }
1942
ram7da5a112014-07-16 20:59:27 +05301943 /**
Wink Savilleef36ef62014-06-11 08:39:38 -07001944 * Death recipient class for monitoring IMS service.
1945 */
1946 private class ImsServiceDeathRecipient implements IBinder.DeathRecipient {
1947 @Override
1948 public void binderDied() {
Brad Ebinger172977a2018-01-16 09:36:56 -08001949 mMmTelFeatureConnection = null;
Wink Savilleef36ef62014-06-11 08:39:38 -07001950 mUt = null;
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -05001951 mConfig = null;
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -07001952 mEcbm = null;
Tyler Gunn4d128b62016-04-13 15:44:38 -07001953 mMultiEndpoint = null;
Wink Savilleef36ef62014-06-11 08:39:38 -07001954 }
1955 }
1956
1957 /**
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -07001958 * Gets the ECBM interface to request ECBM exit.
1959 *
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -07001960 * @return the ECBM interface instance
1961 * @throws ImsException if getting the ECBM interface results in an error
1962 */
Brad Ebinger172977a2018-01-16 09:36:56 -08001963 public ImsEcbm getEcbmInterface() throws ImsException {
Brad Ebinger138b4a62017-06-20 16:29:50 -07001964 if (mEcbm != null && mEcbm.isBinderAlive()) {
1965 return mEcbm;
1966 }
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -07001967
Brad Ebinger138b4a62017-06-20 16:29:50 -07001968 checkAndThrowExceptionIfServiceUnavailable();
1969 try {
Brad Ebinger172977a2018-01-16 09:36:56 -08001970 IImsEcbm iEcbm = mMmTelFeatureConnection.getEcbmInterface();
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -07001971
Brad Ebinger138b4a62017-06-20 16:29:50 -07001972 if (iEcbm == null) {
1973 throw new ImsException("getEcbmInterface()",
1974 ImsReasonInfo.CODE_ECBM_NOT_SUPPORTED);
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -07001975 }
Brad Ebinger138b4a62017-06-20 16:29:50 -07001976 mEcbm = new ImsEcbm(iEcbm);
1977 } catch (RemoteException e) {
1978 throw new ImsException("getEcbmInterface()", e,
1979 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -07001980 }
1981 return mEcbm;
1982 }
Pavel Zhamaitsiak8c065f52015-11-10 14:36:44 -08001983
Mohamed Abdalkader4d68a982018-01-10 13:29:26 -08001984 public void sendSms(int token, int messageRef, String format, String smsc, boolean isRetry,
1985 byte[] pdu) throws ImsException {
1986 try {
Brad Ebinger172977a2018-01-16 09:36:56 -08001987 mMmTelFeatureConnection.sendSms(token, messageRef, format, smsc, isRetry, pdu);
Mohamed Abdalkader4d68a982018-01-10 13:29:26 -08001988 } catch (RemoteException e) {
1989 throw new ImsException("sendSms()", e, ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1990 }
1991 }
1992
1993 public void acknowledgeSms(int token, int messageRef, int result) throws ImsException {
1994 try {
Brad Ebinger172977a2018-01-16 09:36:56 -08001995 mMmTelFeatureConnection.acknowledgeSms(token, messageRef, result);
Mohamed Abdalkader4d68a982018-01-10 13:29:26 -08001996 } catch (RemoteException e) {
1997 throw new ImsException("acknowledgeSms()", e,
1998 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1999 }
2000 }
2001
2002 public void acknowledgeSmsReport(int token, int messageRef, int result) throws ImsException{
2003 try {
Brad Ebinger172977a2018-01-16 09:36:56 -08002004 mMmTelFeatureConnection.acknowledgeSmsReport(token, messageRef, result);
Mohamed Abdalkader4d68a982018-01-10 13:29:26 -08002005 } catch (RemoteException e) {
2006 throw new ImsException("acknowledgeSmsReport()", e,
2007 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
2008 }
2009 }
2010
2011 public String getSmsFormat() throws ImsException{
2012 try {
Brad Ebinger172977a2018-01-16 09:36:56 -08002013 return mMmTelFeatureConnection.getSmsFormat();
Mohamed Abdalkader4d68a982018-01-10 13:29:26 -08002014 } catch (RemoteException e) {
2015 throw new ImsException("getSmsFormat()", e,
2016 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
2017 }
2018 }
2019
2020 public void setSmsListener(IImsSmsListener listener) throws ImsException {
2021 try {
Brad Ebinger172977a2018-01-16 09:36:56 -08002022 mMmTelFeatureConnection.setSmsListener(listener);
Mohamed Abdalkader4d68a982018-01-10 13:29:26 -08002023 } catch (RemoteException e) {
2024 throw new ImsException("setSmsListener()", e,
2025 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
2026 }
2027 }
Mohamed Abdalkadere1453f42018-01-19 19:48:31 -08002028
Mohamed Abdalkader0e734e12018-01-23 13:11:00 -08002029 public void onSmsReady() throws ImsException{
2030 try {
Brad Ebinger190ed932018-01-23 13:41:32 -08002031 mMmTelFeatureConnection.onSmsReady();
Mohamed Abdalkader0e734e12018-01-23 13:11:00 -08002032 } catch (RemoteException e) {
2033 throw new ImsException("onSmsReady()", e,
2034 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
2035 }
2036 }
2037
Pavel Zhamaitsiak8c065f52015-11-10 14:36:44 -08002038 /**
Tyler Gunn4d128b62016-04-13 15:44:38 -07002039 * Gets the Multi-Endpoint interface to subscribe to multi-enpoint notifications..
2040 *
Tyler Gunn4d128b62016-04-13 15:44:38 -07002041 * @return the multi-endpoint interface instance
2042 * @throws ImsException if getting the multi-endpoint interface results in an error
2043 */
Brad Ebinger172977a2018-01-16 09:36:56 -08002044 public ImsMultiEndpoint getMultiEndpointInterface() throws ImsException {
Brad Ebinger138b4a62017-06-20 16:29:50 -07002045 if (mMultiEndpoint != null && mMultiEndpoint.isBinderAlive()) {
2046 return mMultiEndpoint;
Tyler Gunn4d128b62016-04-13 15:44:38 -07002047 }
Brad Ebinger138b4a62017-06-20 16:29:50 -07002048
2049 checkAndThrowExceptionIfServiceUnavailable();
2050 try {
Brad Ebinger172977a2018-01-16 09:36:56 -08002051 IImsMultiEndpoint iImsMultiEndpoint = mMmTelFeatureConnection.getMultiEndpointInterface();
Brad Ebinger138b4a62017-06-20 16:29:50 -07002052
2053 if (iImsMultiEndpoint == null) {
2054 throw new ImsException("getMultiEndpointInterface()",
2055 ImsReasonInfo.CODE_MULTIENDPOINT_NOT_SUPPORTED);
2056 }
2057 mMultiEndpoint = new ImsMultiEndpoint(iImsMultiEndpoint);
2058 } catch (RemoteException e) {
2059 throw new ImsException("getMultiEndpointInterface()", e,
2060 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
2061 }
2062
Tyler Gunn4d128b62016-04-13 15:44:38 -07002063 return mMultiEndpoint;
2064 }
2065
2066 /**
Pavel Zhamaitsiak8c065f52015-11-10 14:36:44 -08002067 * Resets ImsManager settings back to factory defaults.
2068 *
Brad Ebinger479f52c2017-08-28 13:19:22 -07002069 * @deprecated Doesn't support MSIM devices. Use {@link #factoryReset()} instead.
Brad Ebinger16417b42017-03-07 13:48:50 -08002070 *
Pavel Zhamaitsiak8c065f52015-11-10 14:36:44 -08002071 * @hide
2072 */
2073 public static void factoryReset(Context context) {
Brad Ebinger479f52c2017-08-28 13:19:22 -07002074 ImsManager mgr = ImsManager.getInstance(context,
2075 SubscriptionManager.getDefaultVoicePhoneId());
2076 if (mgr != null) {
2077 mgr.factoryReset();
2078 }
2079 loge("factoryReset: ImsManager null.");
Pavel Zhamaitsiak8c065f52015-11-10 14:36:44 -08002080 }
Jack Yu2f102bd2015-12-28 15:31:48 -08002081
Brad Ebinger16417b42017-03-07 13:48:50 -08002082 /**
2083 * Resets ImsManager settings back to factory defaults.
2084 *
2085 * @hide
2086 */
Brad Ebinger479f52c2017-08-28 13:19:22 -07002087 public void factoryReset() {
Brad Ebinger16417b42017-03-07 13:48:50 -08002088 // Set VoLTE to default
Malcolm Chen212ca652017-09-28 17:28:45 -07002089 SubscriptionManager.setSubscriptionProperty(getSubId(),
manabu, shimoda96aee542017-10-06 15:39:36 +09002090 SubscriptionManager.ENHANCED_4G_MODE_ENABLED,
2091 booleanToPropertyString(getBooleanCarrierConfig(
2092 CarrierConfigManager.KEY_ENHANCED_4G_LTE_ON_BY_DEFAULT_BOOL)));
Brad Ebinger16417b42017-03-07 13:48:50 -08002093
2094 // Set VoWiFi to default
Malcolm Chen212ca652017-09-28 17:28:45 -07002095 SubscriptionManager.setSubscriptionProperty(getSubId(),
2096 SubscriptionManager.WFC_IMS_ENABLED,
2097 booleanToPropertyString(getBooleanCarrierConfig(
2098 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ENABLED_BOOL)));
Brad Ebinger16417b42017-03-07 13:48:50 -08002099
2100 // Set VoWiFi mode to default
Malcolm Chen212ca652017-09-28 17:28:45 -07002101 SubscriptionManager.setSubscriptionProperty(getSubId(),
2102 SubscriptionManager.WFC_IMS_MODE,
2103 Integer.toString(getIntCarrierConfig(
2104 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_MODE_INT)));
Brad Ebinger16417b42017-03-07 13:48:50 -08002105
2106 // Set VoWiFi roaming to default
Malcolm Chen212ca652017-09-28 17:28:45 -07002107 SubscriptionManager.setSubscriptionProperty(getSubId(),
2108 SubscriptionManager.WFC_IMS_ROAMING_ENABLED,
2109 booleanToPropertyString(getBooleanCarrierConfig(
2110 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_ENABLED_BOOL)));
Brad Ebinger16417b42017-03-07 13:48:50 -08002111
2112 // Set VT to default
Malcolm Chen212ca652017-09-28 17:28:45 -07002113 SubscriptionManager.setSubscriptionProperty(getSubId(),
2114 SubscriptionManager.VT_IMS_ENABLED, booleanToPropertyString(true));
Brad Ebinger16417b42017-03-07 13:48:50 -08002115
2116 // Push settings to ImsConfig
Brad Ebinger479f52c2017-08-28 13:19:22 -07002117 updateImsServiceConfig(true);
Brad Ebinger16417b42017-03-07 13:48:50 -08002118 }
2119
Amit Mahajan24f7b162016-07-21 16:33:53 -07002120 private boolean isDataEnabled() {
Malcolm Chend0ef12c2017-12-20 11:38:25 -08002121 return new TelephonyManager(mContext, getSubId()).isMobileDataEnabled();
Amit Mahajan24f7b162016-07-21 16:33:53 -07002122 }
2123
2124 private boolean isVolteProvisioned() {
Malcolm Chen18837ff2017-10-25 17:05:41 -07002125 return getProvisionedBoolNoException(
2126 ImsConfig.ConfigConstants.VLT_SETTING_ENABLED);
Amit Mahajan24f7b162016-07-21 16:33:53 -07002127 }
2128
2129 private boolean isWfcProvisioned() {
Malcolm Chen18837ff2017-10-25 17:05:41 -07002130 return getProvisionedBoolNoException(
2131 ImsConfig.ConfigConstants.VOICE_OVER_WIFI_SETTING_ENABLED);
Amit Mahajan24f7b162016-07-21 16:33:53 -07002132 }
2133
2134 private boolean isVtProvisioned() {
Malcolm Chen18837ff2017-10-25 17:05:41 -07002135 return getProvisionedBoolNoException(
2136 ImsConfig.ConfigConstants.LVC_SETTING_ENABLED);
Jack Yu643ffe42016-07-08 14:25:46 -07002137 }
2138
Malcolm Chen212ca652017-09-28 17:28:45 -07002139 private static String booleanToPropertyString(boolean bool) {
2140 return bool ? "1" : "0";
2141 }
2142
2143
Jack Yu2f102bd2015-12-28 15:31:48 -08002144 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
2145 pw.println("ImsManager:");
2146 pw.println(" mPhoneId = " + mPhoneId);
2147 pw.println(" mConfigUpdated = " + mConfigUpdated);
Brad Ebinger172977a2018-01-16 09:36:56 -08002148 pw.println(" mImsServiceProxy = " + mMmTelFeatureConnection);
Amit Mahajan24f7b162016-07-21 16:33:53 -07002149 pw.println(" mDataEnabled = " + isDataEnabled());
Brad Ebinger479f52c2017-08-28 13:19:22 -07002150 pw.println(" ignoreDataEnabledChanged = " + getBooleanCarrierConfig(
Jack Yu57781852016-11-16 17:20:38 -08002151 CarrierConfigManager.KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS));
Jack Yu2f102bd2015-12-28 15:31:48 -08002152
Brad Ebinger479f52c2017-08-28 13:19:22 -07002153 pw.println(" isGbaValid = " + isGbaValid());
Jack Yu2f102bd2015-12-28 15:31:48 -08002154 pw.println(" isImsTurnOffAllowed = " + isImsTurnOffAllowed());
Brad Ebinger479f52c2017-08-28 13:19:22 -07002155 pw.println(" isNonTtyOrTtyOnVolteEnabled = " + isNonTtyOrTtyOnVolteEnabled());
Jack Yu2f102bd2015-12-28 15:31:48 -08002156
Brad Ebinger479f52c2017-08-28 13:19:22 -07002157 pw.println(" isVolteEnabledByPlatform = " + isVolteEnabledByPlatform());
2158 pw.println(" isVolteProvisionedOnDevice = " + isVolteProvisionedOnDevice());
Jack Yu2f102bd2015-12-28 15:31:48 -08002159 pw.println(" isEnhanced4gLteModeSettingEnabledByUser = " +
Brad Ebinger479f52c2017-08-28 13:19:22 -07002160 isEnhanced4gLteModeSettingEnabledByUser());
2161 pw.println(" isVtEnabledByPlatform = " + isVtEnabledByPlatform());
2162 pw.println(" isVtEnabledByUser = " + isVtEnabledByUser());
Jack Yu2f102bd2015-12-28 15:31:48 -08002163
Brad Ebinger479f52c2017-08-28 13:19:22 -07002164 pw.println(" isWfcEnabledByPlatform = " + isWfcEnabledByPlatform());
2165 pw.println(" isWfcEnabledByUser = " + isWfcEnabledByUser());
2166 pw.println(" getWfcMode = " + getWfcMode());
2167 pw.println(" isWfcRoamingEnabledByUser = " + isWfcRoamingEnabledByUser());
Jack Yu2f102bd2015-12-28 15:31:48 -08002168
Brad Ebinger479f52c2017-08-28 13:19:22 -07002169 pw.println(" isVtProvisionedOnDevice = " + isVtProvisionedOnDevice());
2170 pw.println(" isWfcProvisionedOnDevice = " + isWfcProvisionedOnDevice());
Jack Yu2f102bd2015-12-28 15:31:48 -08002171 pw.flush();
2172 }
Wink Savilleef36ef62014-06-11 08:39:38 -07002173}