blob: a267daed498dfe4e4aac06e6acd492174f8b1bb2 [file] [log] [blame]
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001/*
2 * Copyright (C) 2008 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.phone;
18
19import android.app.ActionBar;
20import android.app.Activity;
Evan Charlton1c696832014-04-15 14:24:23 -070021import android.app.ActivityOptions;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070022import android.app.AlertDialog;
23import android.app.Dialog;
24import android.app.ProgressDialog;
25import android.content.ContentResolver;
26import android.content.Context;
27import android.content.DialogInterface;
28import android.content.Intent;
29import android.content.SharedPreferences;
30import android.content.SharedPreferences.Editor;
31import android.content.pm.ActivityInfo;
32import android.content.pm.PackageManager;
33import android.content.pm.ResolveInfo;
34import android.database.Cursor;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070035import android.media.AudioManager;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070036import android.os.AsyncResult;
37import android.os.Bundle;
38import android.os.Handler;
39import android.os.Message;
40import android.os.UserHandle;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070041import android.preference.CheckBoxPreference;
42import android.preference.ListPreference;
43import android.preference.Preference;
44import android.preference.PreferenceActivity;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070045import android.preference.PreferenceManager;
46import android.preference.PreferenceScreen;
47import android.provider.ContactsContract.CommonDataKinds;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070048import android.provider.Settings;
Tyler Gunn4d45d1c2014-09-12 22:17:53 -070049import android.telecom.PhoneAccountHandle;
50import android.telecom.TelecomManager;
Andrew Lee93c345f2014-10-27 15:25:07 -070051import android.telephony.TelephonyManager;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070052import android.text.TextUtils;
53import android.util.Log;
54import android.view.MenuItem;
55import android.view.WindowManager;
56import android.widget.ListAdapter;
57
Andrew Lee312e8172014-10-23 17:01:36 -070058import com.android.ims.ImsManager;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070059import com.android.internal.telephony.CallForwardInfo;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070060import com.android.internal.telephony.Phone;
61import com.android.internal.telephony.PhoneConstants;
Andrew Lee2170a972014-08-13 18:13:01 -070062import com.android.phone.common.util.SettingsUtil;
Andrew Leedb2fe562014-09-03 15:40:43 -070063import com.android.phone.settings.AccountSelectionPreference;
Andrew Lee1af6cf72014-11-04 17:35:26 -080064import com.android.phone.settings.CallForwardInfoUtil;
Andrew Leeb490d732014-10-27 15:00:41 -070065import com.android.phone.settings.VoicemailProviderSettings;
Andrew Lee88b51e22014-10-29 15:48:51 -070066import com.android.phone.settings.VoicemailProviderSettingsUtil;
Andrew Lee5ed870c2014-10-29 11:47:49 -070067import com.android.phone.settings.fdn.FdnSetting;
Sailesh Nepal788959e2014-07-08 23:36:40 -070068import com.android.services.telephony.sip.SipUtil;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070069
Andrew Lee2170a972014-08-13 18:13:01 -070070import java.lang.String;
Andrew Leef1776d82014-11-04 14:45:02 -080071import java.util.ArrayList;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070072import java.util.Collection;
73import java.util.HashMap;
74import java.util.HashSet;
75import java.util.Iterator;
76import java.util.List;
77import java.util.Map;
78
79/**
80 * Top level "Call settings" UI; see res/xml/call_feature_setting.xml
81 *
Andrew Leece8ae2a2014-09-10 10:41:48 -070082 * This preference screen is the root of the "Call settings" hierarchy available from the Phone
83 * app; the settings here let you control various features related to phone calls (including
84 * voicemail settings, the "Respond via SMS" feature, and others.) It's used only on
85 * voice-capable phone devices.
Santos Cordon7d4ddf62013-07-10 11:58:08 -070086 *
87 * Note that this activity is part of the package com.android.phone, even
88 * though you reach it from the "Phone" app (i.e. DialtactsActivity) which
89 * is from the package com.android.contacts.
90 *
91 * For the "Mobile network settings" screen under the main Settings app,
92 * See {@link MobileNetworkSettings}.
93 *
Andrew Leece8ae2a2014-09-10 10:41:48 -070094 * TODO: Settings should be split into PreferenceFragments where possible (ie. voicemail).
Andrew Lee2170a972014-08-13 18:13:01 -070095 *
Santos Cordon7d4ddf62013-07-10 11:58:08 -070096 * @see com.android.phone.MobileNetworkSettings
97 */
98public class CallFeaturesSetting extends PreferenceActivity
99 implements DialogInterface.OnClickListener,
Andrew Lee2170a972014-08-13 18:13:01 -0700100 Preference.OnPreferenceChangeListener,
Andrew Lee2170a972014-08-13 18:13:01 -0700101 EditPhoneNumberPreference.OnDialogClosedListener,
Andrew Leece8ae2a2014-09-10 10:41:48 -0700102 EditPhoneNumberPreference.GetDefaultNumberListener {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700103 private static final String LOG_TAG = "CallFeaturesSetting";
104 private static final boolean DBG = (PhoneGlobals.DBG_LEVEL >= 2);
Andrew Lee77527ac2014-10-21 16:57:39 -0700105 // STOPSHIP if true. Flag to override behavior default behavior to hide VT setting.
106 private static final boolean ENABLE_VT_FLAG = false;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700107
108 /**
109 * Intent action to bring up Voicemail Provider settings.
110 *
111 * @see #IGNORE_PROVIDER_EXTRA
112 */
113 public static final String ACTION_ADD_VOICEMAIL =
114 "com.android.phone.CallFeaturesSetting.ADD_VOICEMAIL";
115 // intent action sent by this activity to a voice mail provider
116 // to trigger its configuration UI
117 public static final String ACTION_CONFIGURE_VOICEMAIL =
118 "com.android.phone.CallFeaturesSetting.CONFIGURE_VOICEMAIL";
119 // Extra put in the return from VM provider config containing voicemail number to set
120 public static final String VM_NUMBER_EXTRA = "com.android.phone.VoicemailNumber";
121 // Extra put in the return from VM provider config containing call forwarding number to set
122 public static final String FWD_NUMBER_EXTRA = "com.android.phone.ForwardingNumber";
123 // Extra put in the return from VM provider config containing call forwarding number to set
124 public static final String FWD_NUMBER_TIME_EXTRA = "com.android.phone.ForwardingNumberTime";
125 // If the VM provider returns non null value in this extra we will force the user to
126 // choose another VM provider
127 public static final String SIGNOUT_EXTRA = "com.android.phone.Signout";
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700128
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700129 // Key identifying the default vocie mail provider
130 public static final String DEFAULT_VM_PROVIDER_KEY = "";
131
132 /**
133 * String Extra put into ACTION_ADD_VOICEMAIL call to indicate which provider should be hidden
134 * in the list of providers presented to the user. This allows a provider which is being
135 * disabled (e.g. GV user logging out) to force the user to pick some other provider.
136 */
137 public static final String IGNORE_PROVIDER_EXTRA = "com.android.phone.ProviderToIgnore";
138
139 // string constants
140 private static final String NUM_PROJECTION[] = {CommonDataKinds.Phone.NUMBER};
141
142 // String keys for preference lookup
143 // TODO: Naming these "BUTTON_*" is confusing since they're not actually buttons(!)
Andrew Lee97708a42014-09-25 12:39:07 -0700144 private static final String VOICEMAIL_SETTING_SCREEN_PREF_KEY = "button_voicemail_category_key";
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700145 private static final String BUTTON_VOICEMAIL_KEY = "button_voicemail_key";
146 private static final String BUTTON_VOICEMAIL_PROVIDER_KEY = "button_voicemail_provider_key";
147 private static final String BUTTON_VOICEMAIL_SETTING_KEY = "button_voicemail_setting_key";
148 // New preference key for voicemail notification vibration
149 /* package */ static final String BUTTON_VOICEMAIL_NOTIFICATION_VIBRATE_KEY =
150 "button_voicemail_notification_vibrate_key";
151 // Old preference key for voicemail notification vibration. Used for migration to the new
152 // preference key only.
153 /* package */ static final String BUTTON_VOICEMAIL_NOTIFICATION_VIBRATE_WHEN_KEY =
154 "button_voicemail_notification_vibrate_when_key";
155 /* package */ static final String BUTTON_VOICEMAIL_NOTIFICATION_RINGTONE_KEY =
156 "button_voicemail_notification_ringtone_key";
157 private static final String BUTTON_FDN_KEY = "button_fdn_key";
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700158
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700159 private static final String BUTTON_DTMF_KEY = "button_dtmf_settings";
160 private static final String BUTTON_RETRY_KEY = "button_auto_retry_key";
161 private static final String BUTTON_TTY_KEY = "button_tty_mode_key";
162 private static final String BUTTON_HAC_KEY = "button_hac_key";
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700163
164 private static final String BUTTON_GSM_UMTS_OPTIONS = "button_gsm_more_expand_key";
165 private static final String BUTTON_CDMA_OPTIONS = "button_cdma_more_expand_key";
166
Andrew Leedb2fe562014-09-03 15:40:43 -0700167 private static final String DEFAULT_OUTGOING_ACCOUNT_KEY = "default_outgoing_account";
Andrew Leece8ae2a2014-09-10 10:41:48 -0700168 private static final String PHONE_ACCOUNT_SETTINGS_KEY =
169 "phone_account_settings_preference_screen";
Andrew Leedb2fe562014-09-03 15:40:43 -0700170
Andrew Leedf14ead2014-10-17 14:22:52 -0700171 private static final String ENABLE_VIDEO_CALLING_KEY = "button_enable_video_calling";
172
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700173 /** Event for Async voicemail change call */
174 private static final int EVENT_VOICEMAIL_CHANGED = 500;
175 private static final int EVENT_FORWARDING_CHANGED = 501;
176 private static final int EVENT_FORWARDING_GET_COMPLETED = 502;
177
Andrew Lee2170a972014-08-13 18:13:01 -0700178 private static final int MSG_UPDATE_VOICEMAIL_RINGTONE_SUMMARY = 1;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700179
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700180 public static final String HAC_KEY = "HACSetting";
181 public static final String HAC_VAL_ON = "ON";
182 public static final String HAC_VAL_OFF = "OFF";
183
184 /** Handle to voicemail pref */
185 private static final int VOICEMAIL_PREF_ID = 1;
186 private static final int VOICEMAIL_PROVIDER_CFG_ID = 2;
187
188 private Phone mPhone;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700189 private AudioManager mAudioManager;
Andrew Lee88b51e22014-10-29 15:48:51 -0700190 private VoicemailProviderSettingsUtil mVmProviderSettingsUtil;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700191
192 private static final int VM_NOCHANGE_ERROR = 400;
193 private static final int VM_RESPONSE_ERROR = 500;
194 private static final int FW_SET_RESPONSE_ERROR = 501;
195 private static final int FW_GET_RESPONSE_ERROR = 502;
196
197
198 // dialog identifiers for voicemail
199 private static final int VOICEMAIL_DIALOG_CONFIRM = 600;
200 private static final int VOICEMAIL_FWD_SAVING_DIALOG = 601;
201 private static final int VOICEMAIL_FWD_READING_DIALOG = 602;
202 private static final int VOICEMAIL_REVERTING_DIALOG = 603;
203
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700204 // voicemail notification vibration string constants
205 private static final String VOICEMAIL_VIBRATION_ALWAYS = "always";
206 private static final String VOICEMAIL_VIBRATION_NEVER = "never";
207
Andrew Lee5ed870c2014-10-29 11:47:49 -0700208 private SubscriptionInfoHelper mSubscriptionInfoHelper;
209
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700210 private EditPhoneNumberPreference mSubMenuVoicemailSettings;
211
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700212 /** Whether dialpad plays DTMF tone or not. */
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700213 private CheckBoxPreference mButtonAutoRetry;
214 private CheckBoxPreference mButtonHAC;
215 private ListPreference mButtonDTMF;
216 private ListPreference mButtonTTY;
Andrew Leece8ae2a2014-09-10 10:41:48 -0700217 private Preference mPhoneAccountSettingsPreference;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700218 private ListPreference mVoicemailProviders;
Andrew Lee97708a42014-09-25 12:39:07 -0700219 private PreferenceScreen mVoicemailSettingsScreen;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700220 private PreferenceScreen mVoicemailSettings;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700221 private CheckBoxPreference mVoicemailNotificationVibrate;
Andrew Leedf14ead2014-10-17 14:22:52 -0700222 private CheckBoxPreference mEnableVideoCalling;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700223
224 private class VoiceMailProvider {
Andrew Leef1776d82014-11-04 14:45:02 -0800225 public String name;
226 public Intent intent;
227
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700228 public VoiceMailProvider(String name, Intent intent) {
229 this.name = name;
230 this.intent = intent;
231 }
Andrew Leef1776d82014-11-04 14:45:02 -0800232
233 public String toString() {
234 return "[ Name: " + name + ", Intent: " + intent + " ]";
235 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700236 }
237
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700238 /**
239 * Results of reading forwarding settings
240 */
241 private CallForwardInfo[] mForwardingReadResults = null;
242
243 /**
244 * Result of forwarding number change.
245 * Keys are reasons (eg. unconditional forwarding).
246 */
247 private Map<Integer, AsyncResult> mForwardingChangeResults = null;
248
249 /**
250 * Expected CF read result types.
251 * This set keeps track of the CF types for which we've issued change
252 * commands so we can tell when we've received all of the responses.
253 */
254 private Collection<Integer> mExpectedChangeResultReasons = null;
255
256 /**
257 * Result of vm number change
258 */
259 private AsyncResult mVoicemailChangeResult = null;
260
261 /**
262 * Previous VM provider setting so we can return to it in case of failure.
263 */
264 private String mPreviousVMProviderKey = null;
265
266 /**
267 * Id of the dialog being currently shown.
268 */
269 private int mCurrentDialogId = 0;
270
271 /**
272 * Flag indicating that we are invoking settings for the voicemail provider programmatically
273 * due to vm provider change.
274 */
275 private boolean mVMProviderSettingsForced = false;
276
277 /**
278 * Flag indicating that we are making changes to vm or fwd numbers
279 * due to vm provider change.
280 */
281 private boolean mChangingVMorFwdDueToProviderChange = false;
282
283 /**
284 * True if we are in the process of vm & fwd number change and vm has already been changed.
285 * This is used to decide what to do in case of rollback.
286 */
287 private boolean mVMChangeCompletedSuccessfully = false;
288
289 /**
290 * True if we had full or partial failure setting forwarding numbers and so need to roll them
291 * back.
292 */
293 private boolean mFwdChangesRequireRollback = false;
294
295 /**
296 * Id of error msg to display to user once we are done reverting the VM provider to the previous
297 * one.
298 */
299 private int mVMOrFwdSetError = 0;
300
301 /**
302 * Data about discovered voice mail settings providers.
303 * Is populated by querying which activities can handle ACTION_CONFIGURE_VOICEMAIL.
304 * They key in this map is package name + activity name.
305 * We always add an entry for the default provider with a key of empty
306 * string and intent value of null.
307 * @see #initVoiceMailProviders()
308 */
309 private final Map<String, VoiceMailProvider> mVMProvidersData =
310 new HashMap<String, VoiceMailProvider>();
311
312 /** string to hold old voicemail number as it is being updated. */
313 private String mOldVmNumber;
314
315 // New call forwarding settings and vm number we will be setting
316 // Need to save these since before we get to saving we need to asynchronously
317 // query the existing forwarding settings.
318 private CallForwardInfo[] mNewFwdSettings;
319 private String mNewVMNumber;
320
321 private boolean mForeground;
322
323 @Override
324 public void onPause() {
325 super.onPause();
326 mForeground = false;
327 }
328
329 /**
330 * We have to pull current settings from the network for all kinds of
331 * voicemail providers so we can tell whether we have to update them,
332 * so use this bit to keep track of whether we're reading settings for the
333 * default provider and should therefore save them out when done.
334 */
335 private boolean mReadingSettingsForDefaultProvider = false;
336
Tyler Gunnbaee2952014-09-10 16:01:02 -0700337 /**
338 * Used to indicate that the voicemail preference should be shown.
339 */
340 private boolean mShowVoicemailPreference = false;
341
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700342 /*
343 * Click Listeners, handle click based on objects attached to UI.
344 */
345
346 // Click listener for all toggle events
347 @Override
348 public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
349 if (preference == mSubMenuVoicemailSettings) {
350 return true;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700351 } else if (preference == mButtonDTMF) {
352 return true;
353 } else if (preference == mButtonTTY) {
354 return true;
355 } else if (preference == mButtonAutoRetry) {
356 android.provider.Settings.Global.putInt(mPhone.getContext().getContentResolver(),
357 android.provider.Settings.Global.CALL_AUTO_RETRY,
358 mButtonAutoRetry.isChecked() ? 1 : 0);
359 return true;
360 } else if (preference == mButtonHAC) {
361 int hac = mButtonHAC.isChecked() ? 1 : 0;
362 // Update HAC value in Settings database
363 Settings.System.putInt(mPhone.getContext().getContentResolver(),
364 Settings.System.HEARING_AID, hac);
365
366 // Update HAC Value in AudioManager
367 mAudioManager.setParameter(HAC_KEY, hac != 0 ? HAC_VAL_ON : HAC_VAL_OFF);
368 return true;
369 } else if (preference == mVoicemailSettings) {
Andrew Lee4ddb9bb2014-11-05 15:03:20 -0800370 if (DBG) log("onPreferenceTreeClick: Voicemail Settings Preference is clicked.");
371
Yorke Leea0f63bf2014-10-09 18:27:20 -0700372 final Dialog dialog = mVoicemailSettings.getDialog();
373 if (dialog != null) {
374 dialog.getActionBar().setDisplayHomeAsUpEnabled(false);
375 }
Andrew Lee4ddb9bb2014-11-05 15:03:20 -0800376
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700377 if (preference.getIntent() != null) {
Andrew Lee4ddb9bb2014-11-05 15:03:20 -0800378 if (DBG) log("Invoking cfg intent " + preference.getIntent().getPackage());
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700379
380 // onActivityResult() will be responsible for resetting some of variables.
381 this.startActivityForResult(preference.getIntent(), VOICEMAIL_PROVIDER_CFG_ID);
382 return true;
383 } else {
Andrew Lee4ddb9bb2014-11-05 15:03:20 -0800384 if (DBG) log("onPreferenceTreeClick(). No intent; use default behavior in xml.");
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700385
Andrew Lee4ddb9bb2014-11-05 15:03:20 -0800386 // onActivityResult() will not be called, so reset variables here.
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700387 mPreviousVMProviderKey = DEFAULT_VM_PROVIDER_KEY;
388 mVMProviderSettingsForced = false;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700389 return false;
390 }
Andrew Lee97708a42014-09-25 12:39:07 -0700391 } else if (preference == mVoicemailSettingsScreen) {
Yorke Leea0f63bf2014-10-09 18:27:20 -0700392 final Dialog dialog = mVoicemailSettingsScreen.getDialog();
393 if (dialog != null) {
394 dialog.getActionBar().setDisplayHomeAsUpEnabled(false);
395 }
Andrew Lee97708a42014-09-25 12:39:07 -0700396 return false;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700397 }
398 return false;
399 }
400
401 /**
402 * Implemented to support onPreferenceChangeListener to look for preference
403 * changes.
404 *
405 * @param preference is the preference to be changed
406 * @param objValue should be the value of the selection, NOT its localized
407 * display value.
408 */
409 @Override
410 public boolean onPreferenceChange(Preference preference, Object objValue) {
Andrew Lee4ddb9bb2014-11-05 15:03:20 -0800411 if (DBG) log("onPreferenceChange: \"" + preference + "\" changed to \"" + objValue + "\"");
Andrew Lee2170a972014-08-13 18:13:01 -0700412
413 if (preference == mButtonDTMF) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700414 int index = mButtonDTMF.findIndexOfValue((String) objValue);
415 Settings.System.putInt(mPhone.getContext().getContentResolver(),
416 Settings.System.DTMF_TONE_TYPE_WHEN_DIALING, index);
417 } else if (preference == mButtonTTY) {
418 handleTTYChange(preference, objValue);
419 } else if (preference == mVoicemailProviders) {
420 final String newProviderKey = (String) objValue;
Andrew Lee4ddb9bb2014-11-05 15:03:20 -0800421
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700422 // If previous provider key and the new one is same, we don't need to handle it.
423 if (mPreviousVMProviderKey.equals(newProviderKey)) {
Andrew Lee4ddb9bb2014-11-05 15:03:20 -0800424 if (DBG) log("No change is made to the VM provider setting.");
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700425 return true;
426 }
427 updateVMPreferenceWidgets(newProviderKey);
428
Andrew Leeb490d732014-10-27 15:00:41 -0700429 final VoicemailProviderSettings newProviderSettings =
Andrew Lee88b51e22014-10-29 15:48:51 -0700430 mVmProviderSettingsUtil.load(newProviderKey);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700431
Andrew Lee88b51e22014-10-29 15:48:51 -0700432 // If the user switches to a voice mail provider and we have numbers stored for it we
433 // will automatically change the phone's voice mail and forwarding number to the stored
434 // ones. Otherwise we will bring up provider's configuration UI.
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700435 if (newProviderSettings == null) {
436 // Force the user into a configuration of the chosen provider
437 Log.w(LOG_TAG, "Saved preferences not found - invoking config");
438 mVMProviderSettingsForced = true;
439 simulatePreferenceClick(mVoicemailSettings);
440 } else {
441 if (DBG) log("Saved preferences found - switching to them");
442 // Set this flag so if we get a failure we revert to previous provider
443 mChangingVMorFwdDueToProviderChange = true;
444 saveVoiceMailAndForwardingNumber(newProviderKey, newProviderSettings);
445 }
Andrew Leedf14ead2014-10-17 14:22:52 -0700446 } else if (preference == mEnableVideoCalling) {
Andrew Lee312e8172014-10-23 17:01:36 -0700447 if (ImsManager.isEnhanced4gLteModeSettingEnabledByUser(mPhone.getContext())) {
448 PhoneGlobals.getInstance().phoneMgr.enableVideoCalling((boolean) objValue);
449 } else {
450 AlertDialog.Builder builder = new AlertDialog.Builder(this);
451 DialogInterface.OnClickListener networkSettingsClickListener =
452 new Dialog.OnClickListener() {
453 @Override
454 public void onClick(DialogInterface dialog, int which) {
455 startActivity(new Intent(mPhone.getContext(),
456 com.android.phone.MobileNetworkSettings.class));
457 }
458 };
459 builder.setMessage(getResources().getString(
460 R.string.enable_video_calling_dialog_msg))
461 .setNeutralButton(getResources().getString(
462 R.string.enable_video_calling_dialog_settings),
463 networkSettingsClickListener)
464 .setPositiveButton(android.R.string.ok, null)
465 .show();
466 return false;
467 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700468 }
Andrew Lee4ddb9bb2014-11-05 15:03:20 -0800469
470 // Always let the preference setting proceed.
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700471 return true;
472 }
473
474 @Override
475 public void onDialogClosed(EditPhoneNumberPreference preference, int buttonClicked) {
Andrew Lee4ddb9bb2014-11-05 15:03:20 -0800476 if (DBG) log("onDialogClosed: Button clicked is " + buttonClicked);
477
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700478 if (buttonClicked == DialogInterface.BUTTON_NEGATIVE) {
479 return;
480 }
481
482 if (preference == mSubMenuVoicemailSettings) {
Andrew Leee438b312014-10-29 16:59:15 -0700483 VoicemailProviderSettings newSettings = new VoicemailProviderSettings(
484 mSubMenuVoicemailSettings.getPhoneNumber(),
485 VoicemailProviderSettings.NO_FORWARDING);
486 saveVoiceMailAndForwardingNumber(getCurrentVoicemailProviderKey(), newSettings);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700487 }
488 }
489
490 /**
491 * Implemented for EditPhoneNumberPreference.GetDefaultNumberListener.
492 * This method set the default values for the various
493 * EditPhoneNumberPreference dialogs.
494 */
495 @Override
496 public String onGetDefaultNumber(EditPhoneNumberPreference preference) {
497 if (preference == mSubMenuVoicemailSettings) {
498 // update the voicemail number field, which takes care of the
499 // mSubMenuVoicemailSettings itself, so we should return null.
500 if (DBG) log("updating default for voicemail dialog");
501 updateVoiceNumberField();
502 return null;
503 }
504
505 String vmDisplay = mPhone.getVoiceMailNumber();
506 if (TextUtils.isEmpty(vmDisplay)) {
507 // if there is no voicemail number, we just return null to
508 // indicate no contribution.
509 return null;
510 }
511
512 // Return the voicemail number prepended with "VM: "
513 if (DBG) log("updating default for call forwarding dialogs");
514 return getString(R.string.voicemail_abbreviated) + " " + vmDisplay;
515 }
516
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700517 private void switchToPreviousVoicemailProvider() {
518 if (DBG) log("switchToPreviousVoicemailProvider " + mPreviousVMProviderKey);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700519
Andrew Lee4ddb9bb2014-11-05 15:03:20 -0800520 if (mPreviousVMProviderKey == null) {
521 return;
522 }
523
524 if (mVMChangeCompletedSuccessfully || mFwdChangesRequireRollback) {
525 showDialogIfForeground(VOICEMAIL_REVERTING_DIALOG);
526 final VoicemailProviderSettings prevSettings =
527 mVmProviderSettingsUtil.load(mPreviousVMProviderKey);
528 if (prevSettings == null) {
529 Log.e(LOG_TAG, "VoicemailProviderSettings for the key \""
530 + mPreviousVMProviderKey + "\" is null but should be loaded.");
531 }
532
533 if (mVMChangeCompletedSuccessfully) {
534 mNewVMNumber = prevSettings.getVoicemailNumber();
535 Log.i(LOG_TAG, "VM change is already completed successfully."
536 + "Have to revert VM back to " + mNewVMNumber + " again.");
537 mPhone.setVoiceMailNumber(
538 mPhone.getVoiceMailAlphaTag().toString(),
539 mNewVMNumber,
540 Message.obtain(mRevertOptionComplete, EVENT_VOICEMAIL_CHANGED));
541 }
542
543 if (mFwdChangesRequireRollback) {
544 Log.i(LOG_TAG, "Requested to rollback forwarding changes.");
545
546 final CallForwardInfo[] prevFwdSettings = prevSettings.getForwardingSettings();
547 if (prevFwdSettings != null) {
548 Map<Integer, AsyncResult> results = mForwardingChangeResults;
549 resetForwardingChangeState();
550 for (int i = 0; i < prevFwdSettings.length; i++) {
551 CallForwardInfo fi = prevFwdSettings[i];
552 if (DBG) log("Reverting fwd #: " + i + ": " + fi.toString());
553 // Only revert the settings for which the update succeeded.
554 AsyncResult result = results.get(fi.reason);
555 if (result != null && result.exception == null) {
556 mExpectedChangeResultReasons.add(fi.reason);
557 CallForwardInfoUtil.setCallForwardingOption(mPhone, fi,
558 mRevertOptionComplete.obtainMessage(
559 EVENT_FORWARDING_CHANGED, i, 0));
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700560 }
561 }
562 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700563 }
Andrew Lee4ddb9bb2014-11-05 15:03:20 -0800564 } else {
565 if (DBG) log("No need to revert");
566 onRevertDone();
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700567 }
568 }
569
570 private void onRevertDone() {
Andrew Lee4ddb9bb2014-11-05 15:03:20 -0800571 if (DBG) log("onRevertDone: Changing provider key back to " + mPreviousVMProviderKey);
572
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700573 updateVMPreferenceWidgets(mPreviousVMProviderKey);
574 updateVoiceNumberField();
575 if (mVMOrFwdSetError != 0) {
Andrew Leeab082272014-11-04 15:50:42 -0800576 showDialogIfForeground(mVMOrFwdSetError);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700577 mVMOrFwdSetError = 0;
578 }
579 }
580
581 @Override
582 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
583 if (DBG) {
584 log("onActivityResult: requestCode: " + requestCode
585 + ", resultCode: " + resultCode
586 + ", data: " + data);
587 }
Andrew Lee4ddb9bb2014-11-05 15:03:20 -0800588
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700589 // there are cases where the contact picker may end up sending us more than one
590 // request. We want to ignore the request if we're not in the correct state.
591 if (requestCode == VOICEMAIL_PROVIDER_CFG_ID) {
592 boolean failure = false;
593
594 // No matter how the processing of result goes lets clear the flag
595 if (DBG) log("mVMProviderSettingsForced: " + mVMProviderSettingsForced);
596 final boolean isVMProviderSettingsForced = mVMProviderSettingsForced;
597 mVMProviderSettingsForced = false;
598
599 String vmNum = null;
600 if (resultCode != RESULT_OK) {
601 if (DBG) log("onActivityResult: vm provider cfg result not OK.");
602 failure = true;
603 } else {
604 if (data == null) {
605 if (DBG) log("onActivityResult: vm provider cfg result has no data");
606 failure = true;
607 } else {
608 if (data.getBooleanExtra(SIGNOUT_EXTRA, false)) {
609 if (DBG) log("Provider requested signout");
610 if (isVMProviderSettingsForced) {
611 if (DBG) log("Going back to previous provider on signout");
612 switchToPreviousVoicemailProvider();
613 } else {
614 final String victim = getCurrentVoicemailProviderKey();
615 if (DBG) log("Relaunching activity and ignoring " + victim);
616 Intent i = new Intent(ACTION_ADD_VOICEMAIL);
617 i.putExtra(IGNORE_PROVIDER_EXTRA, victim);
618 i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
619 this.startActivity(i);
620 }
621 return;
622 }
623 vmNum = data.getStringExtra(VM_NUMBER_EXTRA);
624 if (vmNum == null || vmNum.length() == 0) {
625 if (DBG) log("onActivityResult: vm provider cfg result has no vmnum");
626 failure = true;
627 }
628 }
629 }
630 if (failure) {
Andrew Lee4ddb9bb2014-11-05 15:03:20 -0800631 if (DBG) log("Failure in return from voicemail provider.");
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700632 if (isVMProviderSettingsForced) {
633 switchToPreviousVoicemailProvider();
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700634 }
Andrew Lee4ddb9bb2014-11-05 15:03:20 -0800635
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700636 return;
637 }
638 mChangingVMorFwdDueToProviderChange = isVMProviderSettingsForced;
639 final String fwdNum = data.getStringExtra(FWD_NUMBER_EXTRA);
640
Santos Cordonda120f42014-08-06 04:44:34 -0700641 // TODO: It would be nice to load the current network setting for this and
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700642 // send it to the provider when it's config is invoked so it can use this as default
643 final int fwdNumTime = data.getIntExtra(FWD_NUMBER_TIME_EXTRA, 20);
644
Andrew Lee4ddb9bb2014-11-05 15:03:20 -0800645 if (DBG) log("onActivityResult: cfg result has forwarding number " + fwdNum);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700646 saveVoiceMailAndForwardingNumber(getCurrentVoicemailProviderKey(),
Andrew Leeb490d732014-10-27 15:00:41 -0700647 new VoicemailProviderSettings(vmNum, fwdNum, fwdNumTime));
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700648 return;
649 }
650
651 if (requestCode == VOICEMAIL_PREF_ID) {
652 if (resultCode != RESULT_OK) {
653 if (DBG) log("onActivityResult: contact picker result not OK.");
654 return;
655 }
656
657 Cursor cursor = null;
658 try {
659 cursor = getContentResolver().query(data.getData(),
660 NUM_PROJECTION, null, null, null);
661 if ((cursor == null) || (!cursor.moveToFirst())) {
662 if (DBG) log("onActivityResult: bad contact data, no results found.");
663 return;
664 }
665 mSubMenuVoicemailSettings.onPickActivityResult(cursor.getString(0));
666 return;
667 } finally {
668 if (cursor != null) {
669 cursor.close();
670 }
671 }
672 }
673
674 super.onActivityResult(requestCode, resultCode, data);
675 }
676
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700677 /**
678 * Wrapper around showDialog() that will silently do nothing if we're
679 * not in the foreground.
680 *
681 * This is useful here because most of the dialogs we display from
682 * this class are triggered by asynchronous events (like
683 * success/failure messages from the telephony layer) and it's
684 * possible for those events to come in even after the user has gone
685 * to a different screen.
686 */
687 // TODO: this is too brittle: it's still easy to accidentally add new
688 // code here that calls showDialog() directly (which will result in a
689 // WindowManager$BadTokenException if called after the activity has
690 // been stopped.)
691 //
692 // It would be cleaner to do the "if (mForeground)" check in one
693 // central place, maybe by using a single Handler for all asynchronous
694 // events (and have *that* discard events if we're not in the
695 // foreground.)
696 //
697 // Unfortunately it's not that simple, since we sometimes need to do
698 // actual work to handle these events whether or not we're in the
699 // foreground (see the Handler code in mSetOptionComplete for
700 // example.)
Andrew Leeab082272014-11-04 15:50:42 -0800701 //
702 // TODO: It's a bit worrisome that we don't do anything in error cases when we're not in the
703 // foreground. Consider displaying a toast instead.
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700704 private void showDialogIfForeground(int id) {
705 if (mForeground) {
706 showDialog(id);
707 }
708 }
709
710 private void dismissDialogSafely(int id) {
711 try {
712 dismissDialog(id);
713 } catch (IllegalArgumentException e) {
714 // This is expected in the case where we were in the background
715 // at the time we would normally have shown the dialog, so we didn't
716 // show it.
717 }
718 }
719
Andrew Leeb490d732014-10-27 15:00:41 -0700720 private void saveVoiceMailAndForwardingNumber(
721 String key, VoicemailProviderSettings newSettings) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700722 if (DBG) log("saveVoiceMailAndForwardingNumber: " + newSettings.toString());
Andrew Leeb490d732014-10-27 15:00:41 -0700723 mNewVMNumber = newSettings.getVoicemailNumber();
Andrew Lee4ddb9bb2014-11-05 15:03:20 -0800724 mNewVMNumber = (mNewVMNumber == null) ? "" : mNewVMNumber;
Andrew Leeb490d732014-10-27 15:00:41 -0700725 mNewFwdSettings = newSettings.getForwardingSettings();
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700726
727 // No fwd settings on CDMA
728 if (mPhone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA) {
729 if (DBG) log("ignoring forwarding setting since this is CDMA phone");
Andrew Leeb490d732014-10-27 15:00:41 -0700730 mNewFwdSettings = VoicemailProviderSettings.NO_FORWARDING;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700731 }
732
Andrew Leee3c15212014-10-28 13:12:55 -0700733 // Throw a warning if the voicemail is the same and we did not change forwarding.
Andrew Leeb490d732014-10-27 15:00:41 -0700734 if (mNewVMNumber.equals(mOldVmNumber)
735 && mNewFwdSettings == VoicemailProviderSettings.NO_FORWARDING) {
Andrew Leeab082272014-11-04 15:50:42 -0800736 showDialogIfForeground(VM_NOCHANGE_ERROR);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700737 return;
738 }
739
Andrew Lee88b51e22014-10-29 15:48:51 -0700740 mVmProviderSettingsUtil.save(key, newSettings);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700741 mVMChangeCompletedSuccessfully = false;
742 mFwdChangesRequireRollback = false;
743 mVMOrFwdSetError = 0;
744 if (!key.equals(mPreviousVMProviderKey)) {
745 mReadingSettingsForDefaultProvider =
746 mPreviousVMProviderKey.equals(DEFAULT_VM_PROVIDER_KEY);
747 if (DBG) log("Reading current forwarding settings");
Andrew Leeb490d732014-10-27 15:00:41 -0700748 int numSettingsReasons = VoicemailProviderSettings.FORWARDING_SETTINGS_REASONS.length;
749 mForwardingReadResults = new CallForwardInfo[numSettingsReasons];
750 for (int i = 0; i < mForwardingReadResults.length; i++) {
751 mPhone.getCallForwardingOption(
752 VoicemailProviderSettings.FORWARDING_SETTINGS_REASONS[i],
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700753 mGetOptionComplete.obtainMessage(EVENT_FORWARDING_GET_COMPLETED, i, 0));
754 }
755 showDialogIfForeground(VOICEMAIL_FWD_READING_DIALOG);
756 } else {
757 saveVoiceMailAndForwardingNumberStage2();
758 }
759 }
760
761 private final Handler mGetOptionComplete = new Handler() {
762 @Override
763 public void handleMessage(Message msg) {
764 AsyncResult result = (AsyncResult) msg.obj;
765 switch (msg.what) {
766 case EVENT_FORWARDING_GET_COMPLETED:
767 handleForwardingSettingsReadResult(result, msg.arg1);
768 break;
769 }
770 }
771 };
772
773 private void handleForwardingSettingsReadResult(AsyncResult ar, int idx) {
774 if (DBG) Log.d(LOG_TAG, "handleForwardingSettingsReadResult: " + idx);
Andrew Lee4ddb9bb2014-11-05 15:03:20 -0800775
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700776 Throwable error = null;
777 if (ar.exception != null) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700778 error = ar.exception;
Andrew Lee1af6cf72014-11-04 17:35:26 -0800779 if (DBG) Log.d(LOG_TAG, "FwdRead: ar.exception=" + error.getMessage());
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700780 }
781 if (ar.userObj instanceof Throwable) {
Andrew Lee1af6cf72014-11-04 17:35:26 -0800782 error = (Throwable) ar.userObj;
783 if (DBG) Log.d(LOG_TAG, "FwdRead: userObj=" + error.getMessage());
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700784 }
785
786 // We may have already gotten an error and decided to ignore the other results.
787 if (mForwardingReadResults == null) {
Andrew Lee4ddb9bb2014-11-05 15:03:20 -0800788 if (DBG) Log.d(LOG_TAG, "Ignoring fwd reading result: " + idx);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700789 return;
790 }
791
792 // In case of error ignore other results, show an error dialog
793 if (error != null) {
794 if (DBG) Log.d(LOG_TAG, "Error discovered for fwd read : " + idx);
795 mForwardingReadResults = null;
796 dismissDialogSafely(VOICEMAIL_FWD_READING_DIALOG);
Andrew Leeab082272014-11-04 15:50:42 -0800797 showDialogIfForeground(FW_GET_RESPONSE_ERROR);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700798 return;
799 }
800
Andrew Lee1af6cf72014-11-04 17:35:26 -0800801 // Get the forwarding info.
802 mForwardingReadResults[idx] = CallForwardInfoUtil.getCallForwardInfo(
803 (CallForwardInfo[]) ar.result,
804 VoicemailProviderSettings.FORWARDING_SETTINGS_REASONS[idx]);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700805
806 // Check if we got all the results already
807 boolean done = true;
808 for (int i = 0; i < mForwardingReadResults.length; i++) {
809 if (mForwardingReadResults[i] == null) {
810 done = false;
811 break;
812 }
813 }
Andrew Lee1af6cf72014-11-04 17:35:26 -0800814
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700815 if (done) {
816 if (DBG) Log.d(LOG_TAG, "Done receiving fwd info");
817 dismissDialogSafely(VOICEMAIL_FWD_READING_DIALOG);
Andrew Lee1af6cf72014-11-04 17:35:26 -0800818
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700819 if (mReadingSettingsForDefaultProvider) {
Andrew Lee88b51e22014-10-29 15:48:51 -0700820 mVmProviderSettingsUtil.save(DEFAULT_VM_PROVIDER_KEY,
821 new VoicemailProviderSettings(this.mOldVmNumber, mForwardingReadResults));
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700822 mReadingSettingsForDefaultProvider = false;
823 }
824 saveVoiceMailAndForwardingNumberStage2();
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700825 }
826 }
Andrew Lee4ddb9bb2014-11-05 15:03:20 -0800827
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700828 private void resetForwardingChangeState() {
829 mForwardingChangeResults = new HashMap<Integer, AsyncResult>();
830 mExpectedChangeResultReasons = new HashSet<Integer>();
831 }
832
833 // Called after we are done saving the previous forwarding settings if
834 // we needed.
835 private void saveVoiceMailAndForwardingNumberStage2() {
836 mForwardingChangeResults = null;
837 mVoicemailChangeResult = null;
Andrew Leeb490d732014-10-27 15:00:41 -0700838 if (mNewFwdSettings != VoicemailProviderSettings.NO_FORWARDING) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700839 resetForwardingChangeState();
840 for (int i = 0; i < mNewFwdSettings.length; i++) {
841 CallForwardInfo fi = mNewFwdSettings[i];
Andrew Lee1af6cf72014-11-04 17:35:26 -0800842 CallForwardInfo fiForReason =
843 CallForwardInfoUtil.infoForReason(mForwardingReadResults, fi.reason);
844 final boolean doUpdate = CallForwardInfoUtil.isUpdateRequired(fiForReason, fi);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700845
846 if (doUpdate) {
847 if (DBG) log("Setting fwd #: " + i + ": " + fi.toString());
848 mExpectedChangeResultReasons.add(i);
849
Andrew Lee1af6cf72014-11-04 17:35:26 -0800850 CallForwardInfoUtil.setCallForwardingOption(mPhone, fi,
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700851 mSetOptionComplete.obtainMessage(
852 EVENT_FORWARDING_CHANGED, fi.reason, 0));
853 }
854 }
855 showDialogIfForeground(VOICEMAIL_FWD_SAVING_DIALOG);
856 } else {
857 if (DBG) log("Not touching fwd #");
858 setVMNumberWithCarrier();
859 }
860 }
861
862 private void setVMNumberWithCarrier() {
863 if (DBG) log("save voicemail #: " + mNewVMNumber);
Andrew Lee4ddb9bb2014-11-05 15:03:20 -0800864
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700865 mPhone.setVoiceMailNumber(
866 mPhone.getVoiceMailAlphaTag().toString(),
867 mNewVMNumber,
868 Message.obtain(mSetOptionComplete, EVENT_VOICEMAIL_CHANGED));
869 }
870
871 /**
872 * Callback to handle option update completions
873 */
874 private final Handler mSetOptionComplete = new Handler() {
875 @Override
876 public void handleMessage(Message msg) {
877 AsyncResult result = (AsyncResult) msg.obj;
878 boolean done = false;
879 switch (msg.what) {
880 case EVENT_VOICEMAIL_CHANGED:
881 mVoicemailChangeResult = result;
Andrew Leee438b312014-10-29 16:59:15 -0700882 mVMChangeCompletedSuccessfully = isVmChangeSuccess();
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700883 done = true;
884 break;
885 case EVENT_FORWARDING_CHANGED:
886 mForwardingChangeResults.put(msg.arg1, result);
887 if (result.exception != null) {
888 Log.w(LOG_TAG, "Error in setting fwd# " + msg.arg1 + ": " +
889 result.exception.getMessage());
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700890 }
Andrew Leee438b312014-10-29 16:59:15 -0700891 if (isForwardingCompleted()) {
892 if (isFwdChangeSuccess()) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700893 if (DBG) log("Overall fwd changes completed ok, starting vm change");
894 setVMNumberWithCarrier();
895 } else {
896 Log.w(LOG_TAG, "Overall fwd changes completed in failure. " +
897 "Check if we need to try rollback for some settings.");
898 mFwdChangesRequireRollback = false;
899 Iterator<Map.Entry<Integer,AsyncResult>> it =
900 mForwardingChangeResults.entrySet().iterator();
901 while (it.hasNext()) {
902 Map.Entry<Integer,AsyncResult> entry = it.next();
903 if (entry.getValue().exception == null) {
904 // If at least one succeeded we have to revert
905 Log.i(LOG_TAG, "Rollback will be required");
906 mFwdChangesRequireRollback = true;
907 break;
908 }
909 }
910 if (!mFwdChangesRequireRollback) {
911 Log.i(LOG_TAG, "No rollback needed.");
912 }
913 done = true;
914 }
915 }
916 break;
917 default:
918 // TODO: should never reach this, may want to throw exception
919 }
Andrew Lee4ddb9bb2014-11-05 15:03:20 -0800920
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700921 if (done) {
922 if (DBG) log("All VM provider related changes done");
923 if (mForwardingChangeResults != null) {
924 dismissDialogSafely(VOICEMAIL_FWD_SAVING_DIALOG);
925 }
Andrew Leee438b312014-10-29 16:59:15 -0700926 handleSetVmOrFwdMessage();
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700927 }
928 }
929 };
930
931 /**
932 * Callback to handle option revert completions
933 */
934 private final Handler mRevertOptionComplete = new Handler() {
935 @Override
936 public void handleMessage(Message msg) {
937 AsyncResult result = (AsyncResult) msg.obj;
938 switch (msg.what) {
939 case EVENT_VOICEMAIL_CHANGED:
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700940 if (DBG) log("VM revert complete msg");
Andrew Lee4ddb9bb2014-11-05 15:03:20 -0800941 mVoicemailChangeResult = result;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700942 break;
Andrew Lee4ddb9bb2014-11-05 15:03:20 -0800943
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700944 case EVENT_FORWARDING_CHANGED:
Andrew Lee4ddb9bb2014-11-05 15:03:20 -0800945 if (DBG) log("FWD revert complete msg ");
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700946 mForwardingChangeResults.put(msg.arg1, result);
947 if (result.exception != null) {
948 if (DBG) log("Error in reverting fwd# " + msg.arg1 + ": " +
949 result.exception.getMessage());
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700950 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700951 break;
Andrew Lee4ddb9bb2014-11-05 15:03:20 -0800952
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700953 default:
954 // TODO: should never reach this, may want to throw exception
955 }
Andrew Lee4ddb9bb2014-11-05 15:03:20 -0800956
957 final boolean done = (!mVMChangeCompletedSuccessfully || mVoicemailChangeResult != null)
958 && (!mFwdChangesRequireRollback || isForwardingCompleted());
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700959 if (done) {
960 if (DBG) log("All VM reverts done");
961 dismissDialogSafely(VOICEMAIL_REVERTING_DIALOG);
962 onRevertDone();
963 }
964 }
965 };
966
967 /**
Andrew Leee438b312014-10-29 16:59:15 -0700968 * Return true if there is a change result for every reason for which we expect a result.
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700969 */
Andrew Leee438b312014-10-29 16:59:15 -0700970 private boolean isForwardingCompleted() {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700971 if (mForwardingChangeResults == null) {
Andrew Leee438b312014-10-29 16:59:15 -0700972 return true;
973 }
974
975 for (Integer reason : mExpectedChangeResultReasons) {
976 if (mForwardingChangeResults.get(reason) == null) {
977 return false;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700978 }
979 }
Andrew Leee438b312014-10-29 16:59:15 -0700980
981 return true;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700982 }
Andrew Leee438b312014-10-29 16:59:15 -0700983
984 private boolean isFwdChangeSuccess() {
985 if (mForwardingChangeResults == null) {
986 return true;
987 }
988
989 for (AsyncResult result : mForwardingChangeResults.values()) {
990 Throwable exception = result.exception;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700991 if (exception != null) {
Andrew Leee438b312014-10-29 16:59:15 -0700992 String msg = exception.getMessage();
993 msg = (msg != null) ? msg : "";
994 Log.w(LOG_TAG, "Failed to change forwarding setting. Reason: " + msg);
995 return false;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700996 }
997 }
Andrew Leee438b312014-10-29 16:59:15 -0700998 return true;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700999 }
1000
Andrew Leee438b312014-10-29 16:59:15 -07001001 private boolean isVmChangeSuccess() {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001002 if (mVoicemailChangeResult.exception != null) {
Andrew Leee438b312014-10-29 16:59:15 -07001003 String msg = mVoicemailChangeResult.exception.getMessage();
1004 msg = (msg != null) ? msg : "";
1005 Log.w(LOG_TAG, "Failed to change voicemail. Reason: " + msg);
1006 return false;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001007 }
Andrew Leee438b312014-10-29 16:59:15 -07001008 return true;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001009 }
1010
Andrew Leee438b312014-10-29 16:59:15 -07001011 private void handleSetVmOrFwdMessage() {
1012 if (DBG) log("handleSetVMMessage: set VM request complete");
1013
1014 if (!isFwdChangeSuccess()) {
Andrew Leeab082272014-11-04 15:50:42 -08001015 handleVmOrFwdSetError(FW_SET_RESPONSE_ERROR);
Andrew Leee438b312014-10-29 16:59:15 -07001016 } else if (!isVmChangeSuccess()) {
Andrew Leeab082272014-11-04 15:50:42 -08001017 handleVmOrFwdSetError(VM_RESPONSE_ERROR);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001018 } else {
Andrew Leeab082272014-11-04 15:50:42 -08001019 handleVmAndFwdSetSuccess(VOICEMAIL_DIALOG_CONFIRM);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001020 }
1021 }
1022
1023 /**
1024 * Called when Voicemail Provider or its forwarding settings failed. Rolls back partly made
1025 * changes to those settings and show "failure" dialog.
1026 *
Andrew Leeab082272014-11-04 15:50:42 -08001027 * @param dialogId ID of the dialog to show for the specific error case. Either
1028 * {@link #FW_SET_RESPONSE_ERROR} or {@link #VM_RESPONSE_ERROR}
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001029 */
Andrew Leeab082272014-11-04 15:50:42 -08001030 private void handleVmOrFwdSetError(int dialogId) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001031 if (mChangingVMorFwdDueToProviderChange) {
Andrew Leeab082272014-11-04 15:50:42 -08001032 mVMOrFwdSetError = dialogId;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001033 mChangingVMorFwdDueToProviderChange = false;
1034 switchToPreviousVoicemailProvider();
1035 return;
1036 }
1037 mChangingVMorFwdDueToProviderChange = false;
Andrew Leeab082272014-11-04 15:50:42 -08001038 showDialogIfForeground(dialogId);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001039 updateVoiceNumberField();
1040 }
1041
1042 /**
1043 * Called when Voicemail Provider and its forwarding settings were successfully finished.
1044 * This updates a bunch of variables and show "success" dialog.
1045 */
Andrew Leeab082272014-11-04 15:50:42 -08001046 private void handleVmAndFwdSetSuccess(int dialogId) {
Andrew Lee4ddb9bb2014-11-05 15:03:20 -08001047 if (DBG) log("handleVmAndFwdSetSuccess: key is " + getCurrentVoicemailProviderKey());
1048
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001049 mPreviousVMProviderKey = getCurrentVoicemailProviderKey();
1050 mChangingVMorFwdDueToProviderChange = false;
Andrew Leeab082272014-11-04 15:50:42 -08001051 showDialogIfForeground(dialogId);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001052 updateVoiceNumberField();
1053 }
1054
1055 /**
1056 * Update the voicemail number from what we've recorded on the sim.
1057 */
1058 private void updateVoiceNumberField() {
1059 if (DBG) {
1060 log("updateVoiceNumberField(). mSubMenuVoicemailSettings=" + mSubMenuVoicemailSettings);
1061 }
1062 if (mSubMenuVoicemailSettings == null) {
1063 return;
1064 }
1065
1066 mOldVmNumber = mPhone.getVoiceMailNumber();
1067 if (mOldVmNumber == null) {
1068 mOldVmNumber = "";
1069 }
1070 mSubMenuVoicemailSettings.setPhoneNumber(mOldVmNumber);
1071 final String summary = (mOldVmNumber.length() > 0) ? mOldVmNumber :
1072 getString(R.string.voicemail_number_not_set);
1073 mSubMenuVoicemailSettings.setSummary(summary);
1074 }
1075
1076 /*
1077 * Helper Methods for Activity class.
1078 * The initial query commands are split into two pieces now
1079 * for individual expansion. This combined with the ability
1080 * to cancel queries allows for a much better user experience,
1081 * and also ensures that the user only waits to update the
1082 * data that is relevant.
1083 */
1084
1085 @Override
1086 protected void onPrepareDialog(int id, Dialog dialog) {
1087 super.onPrepareDialog(id, dialog);
1088 mCurrentDialogId = id;
1089 }
1090
1091 // dialog creation method, called by showDialog()
1092 @Override
1093 protected Dialog onCreateDialog(int id) {
1094 if ((id == VM_RESPONSE_ERROR) || (id == VM_NOCHANGE_ERROR) ||
1095 (id == FW_SET_RESPONSE_ERROR) || (id == FW_GET_RESPONSE_ERROR) ||
1096 (id == VOICEMAIL_DIALOG_CONFIRM)) {
1097
1098 AlertDialog.Builder b = new AlertDialog.Builder(this);
1099
1100 int msgId;
1101 int titleId = R.string.error_updating_title;
1102 switch (id) {
1103 case VOICEMAIL_DIALOG_CONFIRM:
1104 msgId = R.string.vm_changed;
1105 titleId = R.string.voicemail;
1106 // Set Button 2
1107 b.setNegativeButton(R.string.close_dialog, this);
1108 break;
1109 case VM_NOCHANGE_ERROR:
1110 // even though this is technically an error,
1111 // keep the title friendly.
1112 msgId = R.string.no_change;
1113 titleId = R.string.voicemail;
1114 // Set Button 2
1115 b.setNegativeButton(R.string.close_dialog, this);
1116 break;
1117 case VM_RESPONSE_ERROR:
1118 msgId = R.string.vm_change_failed;
1119 // Set Button 1
1120 b.setPositiveButton(R.string.close_dialog, this);
1121 break;
1122 case FW_SET_RESPONSE_ERROR:
1123 msgId = R.string.fw_change_failed;
1124 // Set Button 1
1125 b.setPositiveButton(R.string.close_dialog, this);
1126 break;
1127 case FW_GET_RESPONSE_ERROR:
1128 msgId = R.string.fw_get_in_vm_failed;
1129 b.setPositiveButton(R.string.alert_dialog_yes, this);
1130 b.setNegativeButton(R.string.alert_dialog_no, this);
1131 break;
1132 default:
1133 msgId = R.string.exception_error;
1134 // Set Button 3, tells the activity that the error is
1135 // not recoverable on dialog exit.
1136 b.setNeutralButton(R.string.close_dialog, this);
1137 break;
1138 }
1139
1140 b.setTitle(getText(titleId));
1141 String message = getText(msgId).toString();
1142 b.setMessage(message);
1143 b.setCancelable(false);
1144 AlertDialog dialog = b.create();
1145
1146 // make the dialog more obvious by bluring the background.
1147 dialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
1148
1149 return dialog;
1150 } else if (id == VOICEMAIL_FWD_SAVING_DIALOG || id == VOICEMAIL_FWD_READING_DIALOG ||
1151 id == VOICEMAIL_REVERTING_DIALOG) {
1152 ProgressDialog dialog = new ProgressDialog(this);
Andrew Lee5ed870c2014-10-29 11:47:49 -07001153 dialog.setTitle(getText(R.string.call_settings));
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001154 dialog.setIndeterminate(true);
1155 dialog.setCancelable(false);
1156 dialog.setMessage(getText(
1157 id == VOICEMAIL_FWD_SAVING_DIALOG ? R.string.updating_settings :
1158 (id == VOICEMAIL_REVERTING_DIALOG ? R.string.reverting_settings :
1159 R.string.reading_settings)));
1160 return dialog;
1161 }
1162
1163
1164 return null;
1165 }
1166
1167 // This is a method implemented for DialogInterface.OnClickListener.
1168 // Used with the error dialog to close the app, voicemail dialog to just dismiss.
1169 // Close button is mapped to BUTTON_POSITIVE for the errors that close the activity,
1170 // while those that are mapped to BUTTON_NEUTRAL only move the preference focus.
1171 public void onClick(DialogInterface dialog, int which) {
Andrew Lee4ddb9bb2014-11-05 15:03:20 -08001172 if (DBG) log("onClick: button clicked is " + which);
1173
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001174 dialog.dismiss();
1175 switch (which){
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001176 case DialogInterface.BUTTON_NEGATIVE:
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001177 if (mCurrentDialogId == FW_GET_RESPONSE_ERROR) {
1178 // We failed to get current forwarding settings and the user
1179 // does not wish to continue.
1180 switchToPreviousVoicemailProvider();
1181 }
1182 break;
1183 case DialogInterface.BUTTON_POSITIVE:
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001184 if (mCurrentDialogId == FW_GET_RESPONSE_ERROR) {
1185 // We failed to get current forwarding settings but the user
1186 // wishes to continue changing settings to the new vm provider
1187 saveVoiceMailAndForwardingNumberStage2();
1188 } else {
1189 finish();
1190 }
1191 return;
1192 default:
1193 // just let the dialog close and go back to the input
1194 }
Andrew Lee4ddb9bb2014-11-05 15:03:20 -08001195
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001196 // In all dialogs, all buttons except BUTTON_POSITIVE lead to the end of user interaction
1197 // with settings UI. If we were called to explicitly configure voice mail then
1198 // we finish the settings activity here to come back to whatever the user was doing.
1199 if (getIntent().getAction().equals(ACTION_ADD_VOICEMAIL)) {
1200 finish();
1201 }
1202 }
1203
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001204 /*
1205 * Activity class methods
1206 */
1207
1208 @Override
1209 protected void onCreate(Bundle icicle) {
1210 super.onCreate(icicle);
Andrew Lee4ddb9bb2014-11-05 15:03:20 -08001211 if (DBG) log("onCreate: Intent is " + getIntent());
1212
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001213 mPhone = PhoneGlobals.getPhone();
Tyler Gunnbaee2952014-09-10 16:01:02 -07001214 mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
Andrew Lee88b51e22014-10-29 15:48:51 -07001215 mVmProviderSettingsUtil = new VoicemailProviderSettingsUtil(getApplicationContext());
Tyler Gunnbaee2952014-09-10 16:01:02 -07001216
Tyler Gunnbaee2952014-09-10 16:01:02 -07001217 // Show the voicemail preference in onResume if the calling intent specifies the
1218 // ACTION_ADD_VOICEMAIL action.
1219 mShowVoicemailPreference = (icicle == null) &&
1220 getIntent().getAction().equals(ACTION_ADD_VOICEMAIL);
Andrew Lee5ed870c2014-10-29 11:47:49 -07001221
1222 mSubscriptionInfoHelper = new SubscriptionInfoHelper(getIntent());
1223 mSubscriptionInfoHelper.setActionBarTitle(
1224 getActionBar(), getResources(), R.string.call_settings_with_label);
1225 }
Tyler Gunnbaee2952014-09-10 16:01:02 -07001226
1227 private void initPhoneAccountPreferences() {
Andrew Leece8ae2a2014-09-10 10:41:48 -07001228 mPhoneAccountSettingsPreference = findPreference(PHONE_ACCOUNT_SETTINGS_KEY);
Tyler Gunnbaee2952014-09-10 16:01:02 -07001229
Tyler Gunn4d45d1c2014-09-12 22:17:53 -07001230 TelecomManager telecomManager = TelecomManager.from(this);
Andrew Lee93c345f2014-10-27 15:25:07 -07001231 TelephonyManager telephonyManager =
1232 (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
Tyler Gunnbaee2952014-09-10 16:01:02 -07001233
Andrew Lee93c345f2014-10-27 15:25:07 -07001234 if ((telecomManager.getSimCallManagers().isEmpty() && !SipUtil.isVoipSupported(this))
1235 || telephonyManager.getPhoneCount() > 1) {
Andrew Leece8ae2a2014-09-10 10:41:48 -07001236 getPreferenceScreen().removePreference(mPhoneAccountSettingsPreference);
Tyler Gunnbaee2952014-09-10 16:01:02 -07001237 }
1238 }
1239
1240 private boolean canLaunchIntent(Intent intent) {
1241 PackageManager pm = getPackageManager();
1242 return pm.resolveActivity(intent, PackageManager.GET_ACTIVITIES) != null;
1243 }
1244
Tyler Gunnbaee2952014-09-10 16:01:02 -07001245 @Override
1246 protected void onResume() {
1247 super.onResume();
1248 mForeground = true;
1249
1250 PreferenceScreen preferenceScreen = getPreferenceScreen();
1251 if (preferenceScreen != null) {
1252 preferenceScreen.removeAll();
1253 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001254
1255 addPreferencesFromResource(R.xml.call_feature_setting);
Andrew Lee5ed870c2014-10-29 11:47:49 -07001256
Andrew Leedb2fe562014-09-03 15:40:43 -07001257 initPhoneAccountPreferences();
1258
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001259 PreferenceScreen prefSet = getPreferenceScreen();
Andrew Lee64a7d792014-10-15 17:38:38 -07001260 mSubMenuVoicemailSettings = (EditPhoneNumberPreference) findPreference(BUTTON_VOICEMAIL_KEY);
1261 mSubMenuVoicemailSettings.setParentActivity(this, VOICEMAIL_PREF_ID, this);
1262 mSubMenuVoicemailSettings.setDialogOnClosedListener(this);
1263 mSubMenuVoicemailSettings.setDialogTitle(R.string.voicemail_settings_number_label);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001264
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001265 mButtonDTMF = (ListPreference) findPreference(BUTTON_DTMF_KEY);
1266 mButtonAutoRetry = (CheckBoxPreference) findPreference(BUTTON_RETRY_KEY);
1267 mButtonHAC = (CheckBoxPreference) findPreference(BUTTON_HAC_KEY);
1268 mButtonTTY = (ListPreference) findPreference(BUTTON_TTY_KEY);
1269 mVoicemailProviders = (ListPreference) findPreference(BUTTON_VOICEMAIL_PROVIDER_KEY);
Andrew Lee312e8172014-10-23 17:01:36 -07001270 mEnableVideoCalling = (CheckBoxPreference) findPreference(ENABLE_VIDEO_CALLING_KEY);
Andrew Lee2170a972014-08-13 18:13:01 -07001271
Andrew Lee2c027892014-10-29 11:29:54 -07001272 mVoicemailProviders.setOnPreferenceChangeListener(this);
1273 mVoicemailSettingsScreen =
1274 (PreferenceScreen) findPreference(VOICEMAIL_SETTING_SCREEN_PREF_KEY);
1275 mVoicemailSettings = (PreferenceScreen)findPreference(BUTTON_VOICEMAIL_SETTING_KEY);
1276 mVoicemailNotificationVibrate =
1277 (CheckBoxPreference) findPreference(BUTTON_VOICEMAIL_NOTIFICATION_VIBRATE_KEY);
1278 initVoiceMailProviders();
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001279
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001280
Andrew Lee64a7d792014-10-15 17:38:38 -07001281 if (getResources().getBoolean(R.bool.dtmf_type_enabled)) {
1282 mButtonDTMF.setOnPreferenceChangeListener(this);
1283 int dtmf = Settings.System.getInt(getContentResolver(),
1284 Settings.System.DTMF_TONE_TYPE_WHEN_DIALING, Constants.DTMF_TONE_TYPE_NORMAL);
1285 mButtonDTMF.setValueIndex(dtmf);
1286 } else {
1287 prefSet.removePreference(mButtonDTMF);
1288 mButtonDTMF = null;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001289 }
1290
Andrew Lee64a7d792014-10-15 17:38:38 -07001291 if (getResources().getBoolean(R.bool.auto_retry_enabled)) {
1292 mButtonAutoRetry.setOnPreferenceChangeListener(this);
1293 int autoretry = Settings.Global.getInt(
1294 getContentResolver(), Settings.Global.CALL_AUTO_RETRY, 0);
1295 mButtonAutoRetry.setChecked(autoretry != 0);
1296 } else {
1297 prefSet.removePreference(mButtonAutoRetry);
1298 mButtonAutoRetry = null;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001299 }
1300
Andrew Lee64a7d792014-10-15 17:38:38 -07001301 if (getResources().getBoolean(R.bool.hac_enabled)) {
1302 mButtonHAC.setOnPreferenceChangeListener(this);
1303 int hac = Settings.System.getInt(getContentResolver(), Settings.System.HEARING_AID, 0);
1304 mButtonHAC.setChecked(hac != 0);
1305 } else {
1306 prefSet.removePreference(mButtonHAC);
1307 mButtonHAC = null;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001308 }
1309
Andrew Lee64a7d792014-10-15 17:38:38 -07001310 TelecomManager telecomManager = TelecomManager.from(this);
1311 if (telecomManager != null && telecomManager.isTtySupported()) {
1312 mButtonTTY.setOnPreferenceChangeListener(this);
1313 int settingsTtyMode = Settings.Secure.getInt(getContentResolver(),
1314 Settings.Secure.PREFERRED_TTY_MODE,
1315 TelecomManager.TTY_MODE_OFF);
1316 mButtonTTY.setValue(Integer.toString(settingsTtyMode));
1317 updatePreferredTtyModeSummary(settingsTtyMode);
1318 } else {
1319 prefSet.removePreference(mButtonTTY);
1320 mButtonTTY = null;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001321 }
1322
1323 if (!getResources().getBoolean(R.bool.world_phone)) {
1324 Preference options = prefSet.findPreference(BUTTON_CDMA_OPTIONS);
Andrew Lee2170a972014-08-13 18:13:01 -07001325 if (options != null) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001326 prefSet.removePreference(options);
Andrew Lee2170a972014-08-13 18:13:01 -07001327 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001328 options = prefSet.findPreference(BUTTON_GSM_UMTS_OPTIONS);
Andrew Lee2170a972014-08-13 18:13:01 -07001329 if (options != null) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001330 prefSet.removePreference(options);
Andrew Lee2170a972014-08-13 18:13:01 -07001331 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001332
1333 int phoneType = mPhone.getPhoneType();
Andrew Lee5ed870c2014-10-29 11:47:49 -07001334 Preference fdnButton = prefSet.findPreference(BUTTON_FDN_KEY);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001335 if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) {
Andrew Lee5ed870c2014-10-29 11:47:49 -07001336 prefSet.removePreference(fdnButton);
1337
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001338 if (!getResources().getBoolean(R.bool.config_voice_privacy_disable)) {
1339 addPreferencesFromResource(R.xml.cdma_call_privacy);
1340 }
1341 } else if (phoneType == PhoneConstants.PHONE_TYPE_GSM) {
Andrew Lee5ed870c2014-10-29 11:47:49 -07001342 fdnButton.setIntent(mSubscriptionInfoHelper.getIntent(this, FdnSetting.class));
1343
Andrew Lee2170a972014-08-13 18:13:01 -07001344 if (getResources().getBoolean(R.bool.config_additional_call_setting)) {
Etan Cohen0ca1c802014-07-07 15:35:48 -07001345 addPreferencesFromResource(R.xml.gsm_umts_call_options);
1346 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001347 } else {
1348 throw new IllegalStateException("Unexpected phone type: " + phoneType);
1349 }
1350 }
1351
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001352 // check the intent that started this activity and pop up the voicemail
1353 // dialog if we've been asked to.
1354 // If we have at least one non default VM provider registered then bring up
1355 // the selection for the VM provider, otherwise bring up a VM number dialog.
1356 // We only bring up the dialog the first time we are called (not after orientation change)
Andrew Lee2c027892014-10-29 11:29:54 -07001357 if (mShowVoicemailPreference) {
Tyler Gunnbaee2952014-09-10 16:01:02 -07001358 if (DBG) {
1359 log("ACTION_ADD_VOICEMAIL Intent is thrown. current VM data size: "
1360 + mVMProvidersData.size());
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001361 }
Tyler Gunnbaee2952014-09-10 16:01:02 -07001362 if (mVMProvidersData.size() > 1) {
1363 simulatePreferenceClick(mVoicemailProviders);
1364 } else {
1365 onPreferenceChange(mVoicemailProviders, DEFAULT_VM_PROVIDER_KEY);
1366 mVoicemailProviders.setValue(DEFAULT_VM_PROVIDER_KEY);
1367 }
1368 mShowVoicemailPreference = false;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001369 }
Tyler Gunnbaee2952014-09-10 16:01:02 -07001370
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001371 updateVoiceNumberField();
1372 mVMProviderSettingsForced = false;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001373
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001374 SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(
1375 mPhone.getContext());
1376 if (migrateVoicemailVibrationSettingsIfNeeded(prefs)) {
1377 mVoicemailNotificationVibrate.setChecked(prefs.getBoolean(
1378 BUTTON_VOICEMAIL_NOTIFICATION_VIBRATE_KEY, false));
1379 }
1380
Andrew Lee312e8172014-10-23 17:01:36 -07001381 if (ImsManager.isVtEnabledByPlatform(mPhone.getContext()) && ENABLE_VT_FLAG) {
1382 boolean currentValue =
1383 ImsManager.isEnhanced4gLteModeSettingEnabledByUser(mPhone.getContext())
1384 ? PhoneGlobals.getInstance().phoneMgr.isVideoCallingEnabled() : false;
1385 mEnableVideoCalling.setChecked(currentValue);
Andrew Lee77527ac2014-10-21 16:57:39 -07001386 mEnableVideoCalling.setOnPreferenceChangeListener(this);
1387 } else {
1388 prefSet.removePreference(mEnableVideoCalling);
1389 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001390 }
1391
1392 // Migrate settings from BUTTON_VOICEMAIL_NOTIFICATION_VIBRATE_WHEN_KEY to
1393 // BUTTON_VOICEMAIL_NOTIFICATION_VIBRATE_KEY, if the latter does not exist.
1394 // Returns true if migration was performed.
1395 public static boolean migrateVoicemailVibrationSettingsIfNeeded(SharedPreferences prefs) {
1396 if (!prefs.contains(BUTTON_VOICEMAIL_NOTIFICATION_VIBRATE_KEY)) {
1397 String vibrateWhen = prefs.getString(
1398 BUTTON_VOICEMAIL_NOTIFICATION_VIBRATE_WHEN_KEY, VOICEMAIL_VIBRATION_NEVER);
1399 // If vibrateWhen is always, then voicemailVibrate should be True.
1400 // otherwise if vibrateWhen is "only in silent mode", or "never", then
1401 // voicemailVibrate = False.
1402 boolean voicemailVibrate = vibrateWhen.equals(VOICEMAIL_VIBRATION_ALWAYS);
1403 final SharedPreferences.Editor editor = prefs.edit();
1404 editor.putBoolean(BUTTON_VOICEMAIL_NOTIFICATION_VIBRATE_KEY, voicemailVibrate);
1405 editor.commit();
1406 return true;
1407 }
1408 return false;
1409 }
1410
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001411 private void handleTTYChange(Preference preference, Object objValue) {
1412 int buttonTtyMode;
1413 buttonTtyMode = Integer.valueOf((String) objValue).intValue();
1414 int settingsTtyMode = android.provider.Settings.Secure.getInt(
1415 getContentResolver(),
Sailesh Nepalbf900542014-07-15 16:18:32 -07001416 android.provider.Settings.Secure.PREFERRED_TTY_MODE,
Tyler Gunn4d45d1c2014-09-12 22:17:53 -07001417 TelecomManager.TTY_MODE_OFF);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001418 if (DBG) log("handleTTYChange: requesting set TTY mode enable (TTY) to" +
1419 Integer.toString(buttonTtyMode));
1420
1421 if (buttonTtyMode != settingsTtyMode) {
1422 switch(buttonTtyMode) {
Tyler Gunn4d45d1c2014-09-12 22:17:53 -07001423 case TelecomManager.TTY_MODE_OFF:
1424 case TelecomManager.TTY_MODE_FULL:
1425 case TelecomManager.TTY_MODE_HCO:
1426 case TelecomManager.TTY_MODE_VCO:
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001427 android.provider.Settings.Secure.putInt(getContentResolver(),
1428 android.provider.Settings.Secure.PREFERRED_TTY_MODE, buttonTtyMode);
1429 break;
1430 default:
Tyler Gunn4d45d1c2014-09-12 22:17:53 -07001431 buttonTtyMode = TelecomManager.TTY_MODE_OFF;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001432 }
1433
1434 mButtonTTY.setValue(Integer.toString(buttonTtyMode));
1435 updatePreferredTtyModeSummary(buttonTtyMode);
Tyler Gunn4d45d1c2014-09-12 22:17:53 -07001436 Intent ttyModeChanged = new Intent(TelecomManager.ACTION_TTY_PREFERRED_MODE_CHANGED);
1437 ttyModeChanged.putExtra(TelecomManager.EXTRA_TTY_PREFERRED_MODE, buttonTtyMode);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001438 sendBroadcastAsUser(ttyModeChanged, UserHandle.ALL);
1439 }
1440 }
1441
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001442 private void updatePreferredTtyModeSummary(int TtyMode) {
1443 String [] txts = getResources().getStringArray(R.array.tty_mode_entries);
1444 switch(TtyMode) {
Tyler Gunn4d45d1c2014-09-12 22:17:53 -07001445 case TelecomManager.TTY_MODE_OFF:
1446 case TelecomManager.TTY_MODE_HCO:
1447 case TelecomManager.TTY_MODE_VCO:
1448 case TelecomManager.TTY_MODE_FULL:
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001449 mButtonTTY.setSummary(txts[TtyMode]);
1450 break;
1451 default:
1452 mButtonTTY.setEnabled(false);
Tyler Gunn4d45d1c2014-09-12 22:17:53 -07001453 mButtonTTY.setSummary(txts[TelecomManager.TTY_MODE_OFF]);
Sailesh Nepalbf900542014-07-15 16:18:32 -07001454 break;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001455 }
1456 }
1457
1458 private static void log(String msg) {
1459 Log.d(LOG_TAG, msg);
1460 }
1461
1462 /**
1463 * Updates the look of the VM preference widgets based on current VM provider settings.
1464 * Note that the provider name is loaded form the found activity via loadLabel in
1465 * {@link #initVoiceMailProviders()} in order for it to be localizable.
1466 */
1467 private void updateVMPreferenceWidgets(String currentProviderSetting) {
1468 final String key = currentProviderSetting;
1469 final VoiceMailProvider provider = mVMProvidersData.get(key);
1470
1471 /* This is the case when we are coming up on a freshly wiped phone and there is no
1472 persisted value for the list preference mVoicemailProviders.
1473 In this case we want to show the UI asking the user to select a voicemail provider as
1474 opposed to silently falling back to default one. */
1475 if (provider == null) {
Andrew Lee4ddb9bb2014-11-05 15:03:20 -08001476 if (DBG) log("updateVMPreferenceWidget: key: " + key + " -> null.");
1477
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001478 mVoicemailProviders.setSummary(getString(R.string.sum_voicemail_choose_provider));
1479 mVoicemailSettings.setEnabled(false);
1480 mVoicemailSettings.setIntent(null);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001481 mVoicemailNotificationVibrate.setEnabled(false);
1482 } else {
Andrew Lee4ddb9bb2014-11-05 15:03:20 -08001483 if (DBG) log("updateVMPreferenceWidget: key: " + key + " -> " + provider.toString());
1484
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001485 final String providerName = provider.name;
1486 mVoicemailProviders.setSummary(providerName);
1487 mVoicemailSettings.setEnabled(true);
1488 mVoicemailSettings.setIntent(provider.intent);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001489 mVoicemailNotificationVibrate.setEnabled(true);
1490 }
1491 }
1492
1493 /**
1494 * Enumerates existing VM providers and puts their data into the list and populates
1495 * the preference list objects with their names.
1496 * In case we are called with ACTION_ADD_VOICEMAIL intent the intent may have
1497 * an extra string called IGNORE_PROVIDER_EXTRA with "package.activityName" of the provider
1498 * which should be hidden when we bring up the list of possible VM providers to choose.
1499 */
1500 private void initVoiceMailProviders() {
1501 if (DBG) log("initVoiceMailProviders()");
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001502
1503 String providerToIgnore = null;
Andrew Leef1776d82014-11-04 14:45:02 -08001504 if (getIntent().getAction().equals(ACTION_ADD_VOICEMAIL)
1505 && getIntent().hasExtra(IGNORE_PROVIDER_EXTRA)) {
1506 providerToIgnore = getIntent().getStringExtra(IGNORE_PROVIDER_EXTRA);
1507 // Remove this provider from the list.
1508 if (!TextUtils.isEmpty(providerToIgnore)) {
1509 if (DBG) log("Found ACTION_ADD_VOICEMAIL. providerToIgnore= " + providerToIgnore);
Andrew Lee88b51e22014-10-29 15:48:51 -07001510 mVmProviderSettingsUtil.delete(providerToIgnore);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001511 }
1512 }
1513
1514 mVMProvidersData.clear();
1515
Andrew Leef1776d82014-11-04 14:45:02 -08001516 List<String> entries = new ArrayList<String>();
1517 List<String> values = new ArrayList<String>();
1518
1519 // Add default voicemail provider.
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001520 final String myCarrier = getString(R.string.voicemail_default);
1521 mVMProvidersData.put(DEFAULT_VM_PROVIDER_KEY, new VoiceMailProvider(myCarrier, null));
Andrew Leef1776d82014-11-04 14:45:02 -08001522 entries.add(myCarrier);
1523 values.add(DEFAULT_VM_PROVIDER_KEY);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001524
Andrew Leef1776d82014-11-04 14:45:02 -08001525 // Add other voicemail providers.
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001526 PackageManager pm = getPackageManager();
Andrew Leef1776d82014-11-04 14:45:02 -08001527 Intent intent = new Intent(ACTION_CONFIGURE_VOICEMAIL);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001528 List<ResolveInfo> resolveInfos = pm.queryIntentActivities(intent, 0);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001529 for (int i = 0; i < resolveInfos.size(); i++) {
1530 final ResolveInfo ri= resolveInfos.get(i);
1531 final ActivityInfo currentActivityInfo = ri.activityInfo;
Andrew Lee6214e2b2014-11-04 13:57:38 -08001532 final String key = currentActivityInfo.name;
Andrew Leef1776d82014-11-04 14:45:02 -08001533
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001534 if (key.equals(providerToIgnore)) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001535 continue;
1536 }
Andrew Leef1776d82014-11-04 14:45:02 -08001537
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001538 if (DBG) log("Loading key: " + key);
1539 final String nameForDisplay = ri.loadLabel(pm).toString();
1540 Intent providerIntent = new Intent();
1541 providerIntent.setAction(ACTION_CONFIGURE_VOICEMAIL);
Andrew Leef1776d82014-11-04 14:45:02 -08001542 providerIntent.setClassName(currentActivityInfo.packageName, currentActivityInfo.name);
1543 VoiceMailProvider vmProvider = new VoiceMailProvider(nameForDisplay, providerIntent);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001544
Andrew Leef1776d82014-11-04 14:45:02 -08001545 if (DBG) log("Store VoiceMailProvider. Key: " + key + " -> " + vmProvider.toString());
1546 mVMProvidersData.put(key, vmProvider);
1547 entries.add(vmProvider.name);
1548 values.add(key);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001549 }
1550
Andrew Leef1776d82014-11-04 14:45:02 -08001551 mVoicemailProviders.setEntries(entries.toArray(new String[0]));
1552 mVoicemailProviders.setEntryValues(values.toArray(new String[0]));
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001553
Andrew Leef1776d82014-11-04 14:45:02 -08001554 // Remember the current Voicemail Provider key as a "previous" key. This will be used when
1555 // we fail to update Voicemail Provider, which requires rollback. We will update this when
1556 // the VM Provider setting is successfully updated.
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001557 mPreviousVMProviderKey = getCurrentVoicemailProviderKey();
1558 if (DBG) log("Set up the first mPreviousVMProviderKey: " + mPreviousVMProviderKey);
1559
1560 // Finally update the preference texts.
1561 updateVMPreferenceWidgets(mPreviousVMProviderKey);
1562 }
1563
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001564 /**
1565 * Simulates user clicking on a passed preference.
1566 * Usually needed when the preference is a dialog preference and we want to invoke
1567 * a dialog for this preference programmatically.
Santos Cordonda120f42014-08-06 04:44:34 -07001568 * TODO: figure out if there is a cleaner way to cause preference dlg to come up
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001569 */
1570 private void simulatePreferenceClick(Preference preference) {
1571 // Go through settings until we find our setting
1572 // and then simulate a click on it to bring up the dialog
1573 final ListAdapter adapter = getPreferenceScreen().getRootAdapter();
1574 for (int idx = 0; idx < adapter.getCount(); idx++) {
1575 if (adapter.getItem(idx) == preference) {
1576 getPreferenceScreen().onItemClick(this.getListView(),
1577 null, idx, adapter.getItemId(idx));
1578 break;
1579 }
1580 }
1581 }
1582
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001583 private String getCurrentVoicemailProviderKey() {
1584 final String key = mVoicemailProviders.getValue();
1585 return (key != null) ? key : DEFAULT_VM_PROVIDER_KEY;
1586 }
1587
1588 @Override
1589 public boolean onOptionsItemSelected(MenuItem item) {
1590 final int itemId = item.getItemId();
1591 if (itemId == android.R.id.home) { // See ActionBar#setDisplayHomeAsUpEnabled()
Yorke Leef2d0cac2013-09-09 19:42:56 -07001592 onBackPressed();
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001593 return true;
1594 }
1595 return super.onOptionsItemSelected(item);
1596 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001597 /**
1598 * Finish current Activity and go up to the top level Settings ({@link CallFeaturesSetting}).
1599 * This is useful for implementing "HomeAsUp" capability for second-level Settings.
1600 */
1601 public static void goUpToTopLevelSetting(Activity activity) {
1602 Intent intent = new Intent(activity, CallFeaturesSetting.class);
1603 intent.setAction(Intent.ACTION_MAIN);
1604 intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
1605 activity.startActivity(intent);
1606 activity.finish();
1607 }
1608}