blob: 74c9e2f31efa459c7237913352aa4f1ddf79eafd [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;
60import com.android.internal.telephony.CommandsInterface;
61import com.android.internal.telephony.Phone;
62import com.android.internal.telephony.PhoneConstants;
Andrew Lee2170a972014-08-13 18:13:01 -070063import com.android.phone.common.util.SettingsUtil;
Andrew Leedb2fe562014-09-03 15:40:43 -070064import com.android.phone.settings.AccountSelectionPreference;
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;
Sailesh Nepal788959e2014-07-08 23:36:40 -070067import com.android.services.telephony.sip.SipUtil;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070068
Andrew Lee2170a972014-08-13 18:13:01 -070069import java.lang.String;
Andrew Leef1776d82014-11-04 14:45:02 -080070import java.util.ArrayList;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070071import java.util.Collection;
72import java.util.HashMap;
73import java.util.HashSet;
74import java.util.Iterator;
75import java.util.List;
76import java.util.Map;
77
78/**
79 * Top level "Call settings" UI; see res/xml/call_feature_setting.xml
80 *
Andrew Leece8ae2a2014-09-10 10:41:48 -070081 * This preference screen is the root of the "Call settings" hierarchy available from the Phone
82 * app; the settings here let you control various features related to phone calls (including
83 * voicemail settings, the "Respond via SMS" feature, and others.) It's used only on
84 * voice-capable phone devices.
Santos Cordon7d4ddf62013-07-10 11:58:08 -070085 *
86 * Note that this activity is part of the package com.android.phone, even
87 * though you reach it from the "Phone" app (i.e. DialtactsActivity) which
88 * is from the package com.android.contacts.
89 *
90 * For the "Mobile network settings" screen under the main Settings app,
91 * See {@link MobileNetworkSettings}.
92 *
Andrew Leece8ae2a2014-09-10 10:41:48 -070093 * TODO: Settings should be split into PreferenceFragments where possible (ie. voicemail).
Andrew Lee2170a972014-08-13 18:13:01 -070094 *
Santos Cordon7d4ddf62013-07-10 11:58:08 -070095 * @see com.android.phone.MobileNetworkSettings
96 */
97public class CallFeaturesSetting extends PreferenceActivity
98 implements DialogInterface.OnClickListener,
Andrew Lee2170a972014-08-13 18:13:01 -070099 Preference.OnPreferenceChangeListener,
Andrew Lee2170a972014-08-13 18:13:01 -0700100 EditPhoneNumberPreference.OnDialogClosedListener,
Andrew Leece8ae2a2014-09-10 10:41:48 -0700101 EditPhoneNumberPreference.GetDefaultNumberListener {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700102 private static final String LOG_TAG = "CallFeaturesSetting";
103 private static final boolean DBG = (PhoneGlobals.DBG_LEVEL >= 2);
Andrew Lee77527ac2014-10-21 16:57:39 -0700104 // STOPSHIP if true. Flag to override behavior default behavior to hide VT setting.
105 private static final boolean ENABLE_VT_FLAG = false;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700106
107 /**
108 * Intent action to bring up Voicemail Provider settings.
109 *
110 * @see #IGNORE_PROVIDER_EXTRA
111 */
112 public static final String ACTION_ADD_VOICEMAIL =
113 "com.android.phone.CallFeaturesSetting.ADD_VOICEMAIL";
114 // intent action sent by this activity to a voice mail provider
115 // to trigger its configuration UI
116 public static final String ACTION_CONFIGURE_VOICEMAIL =
117 "com.android.phone.CallFeaturesSetting.CONFIGURE_VOICEMAIL";
Andrew Leee3c15212014-10-28 13:12:55 -0700118 // Extra on intent to Call Settings containing the id of the subscription to modify.
119 public static final String SUB_ID_EXTRA =
120 "com.android.phone.CallFeaturesSetting.SubscriptionId";
121 // Extra on intent to Call Settings containing the label of the subscription to modify.
122 public static final String SUB_LABEL_EXTRA =
123 "com.android.phone.CallFeaturesSetting.SubscriptionLabel";
124
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700125 // Extra put in the return from VM provider config containing voicemail number to set
126 public static final String VM_NUMBER_EXTRA = "com.android.phone.VoicemailNumber";
127 // Extra put in the return from VM provider config containing call forwarding number to set
128 public static final String FWD_NUMBER_EXTRA = "com.android.phone.ForwardingNumber";
129 // Extra put in the return from VM provider config containing call forwarding number to set
130 public static final String FWD_NUMBER_TIME_EXTRA = "com.android.phone.ForwardingNumberTime";
131 // If the VM provider returns non null value in this extra we will force the user to
132 // choose another VM provider
133 public static final String SIGNOUT_EXTRA = "com.android.phone.Signout";
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700134
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700135 // Key identifying the default vocie mail provider
136 public static final String DEFAULT_VM_PROVIDER_KEY = "";
137
138 /**
139 * String Extra put into ACTION_ADD_VOICEMAIL call to indicate which provider should be hidden
140 * in the list of providers presented to the user. This allows a provider which is being
141 * disabled (e.g. GV user logging out) to force the user to pick some other provider.
142 */
143 public static final String IGNORE_PROVIDER_EXTRA = "com.android.phone.ProviderToIgnore";
144
145 // string constants
146 private static final String NUM_PROJECTION[] = {CommonDataKinds.Phone.NUMBER};
147
148 // String keys for preference lookup
149 // TODO: Naming these "BUTTON_*" is confusing since they're not actually buttons(!)
Andrew Lee97708a42014-09-25 12:39:07 -0700150 private static final String VOICEMAIL_SETTING_SCREEN_PREF_KEY = "button_voicemail_category_key";
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700151 private static final String BUTTON_VOICEMAIL_KEY = "button_voicemail_key";
152 private static final String BUTTON_VOICEMAIL_PROVIDER_KEY = "button_voicemail_provider_key";
153 private static final String BUTTON_VOICEMAIL_SETTING_KEY = "button_voicemail_setting_key";
154 // New preference key for voicemail notification vibration
155 /* package */ static final String BUTTON_VOICEMAIL_NOTIFICATION_VIBRATE_KEY =
156 "button_voicemail_notification_vibrate_key";
157 // Old preference key for voicemail notification vibration. Used for migration to the new
158 // preference key only.
159 /* package */ static final String BUTTON_VOICEMAIL_NOTIFICATION_VIBRATE_WHEN_KEY =
160 "button_voicemail_notification_vibrate_when_key";
161 /* package */ static final String BUTTON_VOICEMAIL_NOTIFICATION_RINGTONE_KEY =
162 "button_voicemail_notification_ringtone_key";
163 private static final String BUTTON_FDN_KEY = "button_fdn_key";
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700164
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700165 private static final String BUTTON_DTMF_KEY = "button_dtmf_settings";
166 private static final String BUTTON_RETRY_KEY = "button_auto_retry_key";
167 private static final String BUTTON_TTY_KEY = "button_tty_mode_key";
168 private static final String BUTTON_HAC_KEY = "button_hac_key";
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700169
170 private static final String BUTTON_GSM_UMTS_OPTIONS = "button_gsm_more_expand_key";
171 private static final String BUTTON_CDMA_OPTIONS = "button_cdma_more_expand_key";
172
Andrew Leedb2fe562014-09-03 15:40:43 -0700173 private static final String DEFAULT_OUTGOING_ACCOUNT_KEY = "default_outgoing_account";
Andrew Leece8ae2a2014-09-10 10:41:48 -0700174 private static final String PHONE_ACCOUNT_SETTINGS_KEY =
175 "phone_account_settings_preference_screen";
Andrew Leedb2fe562014-09-03 15:40:43 -0700176
Andrew Leedf14ead2014-10-17 14:22:52 -0700177 private static final String ENABLE_VIDEO_CALLING_KEY = "button_enable_video_calling";
178
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700179 /** Event for Async voicemail change call */
180 private static final int EVENT_VOICEMAIL_CHANGED = 500;
181 private static final int EVENT_FORWARDING_CHANGED = 501;
182 private static final int EVENT_FORWARDING_GET_COMPLETED = 502;
183
Andrew Lee2170a972014-08-13 18:13:01 -0700184 private static final int MSG_UPDATE_VOICEMAIL_RINGTONE_SUMMARY = 1;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700185
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700186 public static final String HAC_KEY = "HACSetting";
187 public static final String HAC_VAL_ON = "ON";
188 public static final String HAC_VAL_OFF = "OFF";
189
190 /** Handle to voicemail pref */
191 private static final int VOICEMAIL_PREF_ID = 1;
192 private static final int VOICEMAIL_PROVIDER_CFG_ID = 2;
193
194 private Phone mPhone;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700195 private AudioManager mAudioManager;
Andrew Lee88b51e22014-10-29 15:48:51 -0700196 private VoicemailProviderSettingsUtil mVmProviderSettingsUtil;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700197
198 private static final int VM_NOCHANGE_ERROR = 400;
199 private static final int VM_RESPONSE_ERROR = 500;
200 private static final int FW_SET_RESPONSE_ERROR = 501;
201 private static final int FW_GET_RESPONSE_ERROR = 502;
202
203
204 // dialog identifiers for voicemail
205 private static final int VOICEMAIL_DIALOG_CONFIRM = 600;
206 private static final int VOICEMAIL_FWD_SAVING_DIALOG = 601;
207 private static final int VOICEMAIL_FWD_READING_DIALOG = 602;
208 private static final int VOICEMAIL_REVERTING_DIALOG = 603;
209
Andrew Leee438b312014-10-29 16:59:15 -0700210 /**
211 * @see CallForwardInfo#status
212 */
213 private static final int CALL_FORWARD_INFO_INACTIVE_STATUS = 0;
214
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700215 // voicemail notification vibration string constants
216 private static final String VOICEMAIL_VIBRATION_ALWAYS = "always";
217 private static final String VOICEMAIL_VIBRATION_NEVER = "never";
218
219 private EditPhoneNumberPreference mSubMenuVoicemailSettings;
220
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700221 /** Whether dialpad plays DTMF tone or not. */
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700222 private CheckBoxPreference mButtonAutoRetry;
223 private CheckBoxPreference mButtonHAC;
224 private ListPreference mButtonDTMF;
225 private ListPreference mButtonTTY;
Andrew Leece8ae2a2014-09-10 10:41:48 -0700226 private Preference mPhoneAccountSettingsPreference;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700227 private ListPreference mVoicemailProviders;
Andrew Lee97708a42014-09-25 12:39:07 -0700228 private PreferenceScreen mVoicemailSettingsScreen;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700229 private PreferenceScreen mVoicemailSettings;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700230 private CheckBoxPreference mVoicemailNotificationVibrate;
Andrew Leedf14ead2014-10-17 14:22:52 -0700231 private CheckBoxPreference mEnableVideoCalling;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700232
233 private class VoiceMailProvider {
Andrew Leef1776d82014-11-04 14:45:02 -0800234 public String name;
235 public Intent intent;
236
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700237 public VoiceMailProvider(String name, Intent intent) {
238 this.name = name;
239 this.intent = intent;
240 }
Andrew Leef1776d82014-11-04 14:45:02 -0800241
242 public String toString() {
243 return "[ Name: " + name + ", Intent: " + intent + " ]";
244 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700245 }
246
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700247 /**
248 * Results of reading forwarding settings
249 */
250 private CallForwardInfo[] mForwardingReadResults = null;
251
252 /**
253 * Result of forwarding number change.
254 * Keys are reasons (eg. unconditional forwarding).
255 */
256 private Map<Integer, AsyncResult> mForwardingChangeResults = null;
257
258 /**
259 * Expected CF read result types.
260 * This set keeps track of the CF types for which we've issued change
261 * commands so we can tell when we've received all of the responses.
262 */
263 private Collection<Integer> mExpectedChangeResultReasons = null;
264
265 /**
266 * Result of vm number change
267 */
268 private AsyncResult mVoicemailChangeResult = null;
269
270 /**
271 * Previous VM provider setting so we can return to it in case of failure.
272 */
273 private String mPreviousVMProviderKey = null;
274
275 /**
276 * Id of the dialog being currently shown.
277 */
278 private int mCurrentDialogId = 0;
279
280 /**
281 * Flag indicating that we are invoking settings for the voicemail provider programmatically
282 * due to vm provider change.
283 */
284 private boolean mVMProviderSettingsForced = false;
285
286 /**
287 * Flag indicating that we are making changes to vm or fwd numbers
288 * due to vm provider change.
289 */
290 private boolean mChangingVMorFwdDueToProviderChange = false;
291
292 /**
293 * True if we are in the process of vm & fwd number change and vm has already been changed.
294 * This is used to decide what to do in case of rollback.
295 */
296 private boolean mVMChangeCompletedSuccessfully = false;
297
298 /**
299 * True if we had full or partial failure setting forwarding numbers and so need to roll them
300 * back.
301 */
302 private boolean mFwdChangesRequireRollback = false;
303
304 /**
305 * Id of error msg to display to user once we are done reverting the VM provider to the previous
306 * one.
307 */
308 private int mVMOrFwdSetError = 0;
309
310 /**
311 * Data about discovered voice mail settings providers.
312 * Is populated by querying which activities can handle ACTION_CONFIGURE_VOICEMAIL.
313 * They key in this map is package name + activity name.
314 * We always add an entry for the default provider with a key of empty
315 * string and intent value of null.
316 * @see #initVoiceMailProviders()
317 */
318 private final Map<String, VoiceMailProvider> mVMProvidersData =
319 new HashMap<String, VoiceMailProvider>();
320
321 /** string to hold old voicemail number as it is being updated. */
322 private String mOldVmNumber;
323
324 // New call forwarding settings and vm number we will be setting
325 // Need to save these since before we get to saving we need to asynchronously
326 // query the existing forwarding settings.
327 private CallForwardInfo[] mNewFwdSettings;
328 private String mNewVMNumber;
329
330 private boolean mForeground;
331
332 @Override
333 public void onPause() {
334 super.onPause();
335 mForeground = false;
336 }
337
338 /**
339 * We have to pull current settings from the network for all kinds of
340 * voicemail providers so we can tell whether we have to update them,
341 * so use this bit to keep track of whether we're reading settings for the
342 * default provider and should therefore save them out when done.
343 */
344 private boolean mReadingSettingsForDefaultProvider = false;
345
Tyler Gunnbaee2952014-09-10 16:01:02 -0700346 /**
347 * Used to indicate that the voicemail preference should be shown.
348 */
349 private boolean mShowVoicemailPreference = false;
350
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700351 /*
352 * Click Listeners, handle click based on objects attached to UI.
353 */
354
355 // Click listener for all toggle events
356 @Override
357 public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
358 if (preference == mSubMenuVoicemailSettings) {
359 return true;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700360 } else if (preference == mButtonDTMF) {
361 return true;
362 } else if (preference == mButtonTTY) {
363 return true;
364 } else if (preference == mButtonAutoRetry) {
365 android.provider.Settings.Global.putInt(mPhone.getContext().getContentResolver(),
366 android.provider.Settings.Global.CALL_AUTO_RETRY,
367 mButtonAutoRetry.isChecked() ? 1 : 0);
368 return true;
369 } else if (preference == mButtonHAC) {
370 int hac = mButtonHAC.isChecked() ? 1 : 0;
371 // Update HAC value in Settings database
372 Settings.System.putInt(mPhone.getContext().getContentResolver(),
373 Settings.System.HEARING_AID, hac);
374
375 // Update HAC Value in AudioManager
376 mAudioManager.setParameter(HAC_KEY, hac != 0 ? HAC_VAL_ON : HAC_VAL_OFF);
377 return true;
378 } else if (preference == mVoicemailSettings) {
Yorke Leea0f63bf2014-10-09 18:27:20 -0700379 final Dialog dialog = mVoicemailSettings.getDialog();
380 if (dialog != null) {
381 dialog.getActionBar().setDisplayHomeAsUpEnabled(false);
382 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700383 if (DBG) log("onPreferenceTreeClick: Voicemail Settings Preference is clicked.");
384 if (preference.getIntent() != null) {
385 if (DBG) {
386 log("onPreferenceTreeClick: Invoking cfg intent "
387 + preference.getIntent().getPackage());
388 }
389
390 // onActivityResult() will be responsible for resetting some of variables.
391 this.startActivityForResult(preference.getIntent(), VOICEMAIL_PROVIDER_CFG_ID);
392 return true;
393 } else {
394 if (DBG) {
395 log("onPreferenceTreeClick:"
396 + " No Intent is available. Use default behavior defined in xml.");
397 }
398
399 // There's no onActivityResult(), so we need to take care of some of variables
400 // which should be reset here.
401 mPreviousVMProviderKey = DEFAULT_VM_PROVIDER_KEY;
402 mVMProviderSettingsForced = false;
403
404 // This should let the preference use default behavior in the xml.
405 return false;
406 }
Andrew Lee97708a42014-09-25 12:39:07 -0700407 } else if (preference == mVoicemailSettingsScreen) {
Yorke Leea0f63bf2014-10-09 18:27:20 -0700408 final Dialog dialog = mVoicemailSettingsScreen.getDialog();
409 if (dialog != null) {
410 dialog.getActionBar().setDisplayHomeAsUpEnabled(false);
411 }
Andrew Lee97708a42014-09-25 12:39:07 -0700412 return false;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700413 }
414 return false;
415 }
416
417 /**
418 * Implemented to support onPreferenceChangeListener to look for preference
419 * changes.
420 *
421 * @param preference is the preference to be changed
422 * @param objValue should be the value of the selection, NOT its localized
423 * display value.
424 */
425 @Override
426 public boolean onPreferenceChange(Preference preference, Object objValue) {
427 if (DBG) {
Andrew Leedf14ead2014-10-17 14:22:52 -0700428 log("onPreferenceChange(). preference: \"" + preference + "\""
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700429 + ", value: \"" + objValue + "\"");
430 }
Andrew Lee2170a972014-08-13 18:13:01 -0700431
432 if (preference == mButtonDTMF) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700433 int index = mButtonDTMF.findIndexOfValue((String) objValue);
434 Settings.System.putInt(mPhone.getContext().getContentResolver(),
435 Settings.System.DTMF_TONE_TYPE_WHEN_DIALING, index);
436 } else if (preference == mButtonTTY) {
437 handleTTYChange(preference, objValue);
438 } else if (preference == mVoicemailProviders) {
439 final String newProviderKey = (String) objValue;
440 if (DBG) {
441 log("Voicemail Provider changes from \"" + mPreviousVMProviderKey
442 + "\" to \"" + newProviderKey + "\".");
443 }
444 // If previous provider key and the new one is same, we don't need to handle it.
445 if (mPreviousVMProviderKey.equals(newProviderKey)) {
446 if (DBG) log("No change is made toward VM provider setting.");
447 return true;
448 }
449 updateVMPreferenceWidgets(newProviderKey);
450
Andrew Leeb490d732014-10-27 15:00:41 -0700451 final VoicemailProviderSettings newProviderSettings =
Andrew Lee88b51e22014-10-29 15:48:51 -0700452 mVmProviderSettingsUtil.load(newProviderKey);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700453
Andrew Lee88b51e22014-10-29 15:48:51 -0700454 // If the user switches to a voice mail provider and we have numbers stored for it we
455 // will automatically change the phone's voice mail and forwarding number to the stored
456 // ones. Otherwise we will bring up provider's configuration UI.
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700457 if (newProviderSettings == null) {
458 // Force the user into a configuration of the chosen provider
459 Log.w(LOG_TAG, "Saved preferences not found - invoking config");
460 mVMProviderSettingsForced = true;
461 simulatePreferenceClick(mVoicemailSettings);
462 } else {
463 if (DBG) log("Saved preferences found - switching to them");
464 // Set this flag so if we get a failure we revert to previous provider
465 mChangingVMorFwdDueToProviderChange = true;
466 saveVoiceMailAndForwardingNumber(newProviderKey, newProviderSettings);
467 }
Andrew Leedf14ead2014-10-17 14:22:52 -0700468 } else if (preference == mEnableVideoCalling) {
Andrew Lee312e8172014-10-23 17:01:36 -0700469 if (ImsManager.isEnhanced4gLteModeSettingEnabledByUser(mPhone.getContext())) {
470 PhoneGlobals.getInstance().phoneMgr.enableVideoCalling((boolean) objValue);
471 } else {
472 AlertDialog.Builder builder = new AlertDialog.Builder(this);
473 DialogInterface.OnClickListener networkSettingsClickListener =
474 new Dialog.OnClickListener() {
475 @Override
476 public void onClick(DialogInterface dialog, int which) {
477 startActivity(new Intent(mPhone.getContext(),
478 com.android.phone.MobileNetworkSettings.class));
479 }
480 };
481 builder.setMessage(getResources().getString(
482 R.string.enable_video_calling_dialog_msg))
483 .setNeutralButton(getResources().getString(
484 R.string.enable_video_calling_dialog_settings),
485 networkSettingsClickListener)
486 .setPositiveButton(android.R.string.ok, null)
487 .show();
488 return false;
489 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700490 }
491 // always let the preference setting proceed.
492 return true;
493 }
494
495 @Override
496 public void onDialogClosed(EditPhoneNumberPreference preference, int buttonClicked) {
497 if (DBG) log("onPreferenceClick: request preference click on dialog close: " +
498 buttonClicked);
499 if (buttonClicked == DialogInterface.BUTTON_NEGATIVE) {
500 return;
501 }
502
503 if (preference == mSubMenuVoicemailSettings) {
Andrew Leee438b312014-10-29 16:59:15 -0700504 VoicemailProviderSettings newSettings = new VoicemailProviderSettings(
505 mSubMenuVoicemailSettings.getPhoneNumber(),
506 VoicemailProviderSettings.NO_FORWARDING);
507 saveVoiceMailAndForwardingNumber(getCurrentVoicemailProviderKey(), newSettings);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700508 }
509 }
510
511 /**
512 * Implemented for EditPhoneNumberPreference.GetDefaultNumberListener.
513 * This method set the default values for the various
514 * EditPhoneNumberPreference dialogs.
515 */
516 @Override
517 public String onGetDefaultNumber(EditPhoneNumberPreference preference) {
518 if (preference == mSubMenuVoicemailSettings) {
519 // update the voicemail number field, which takes care of the
520 // mSubMenuVoicemailSettings itself, so we should return null.
521 if (DBG) log("updating default for voicemail dialog");
522 updateVoiceNumberField();
523 return null;
524 }
525
526 String vmDisplay = mPhone.getVoiceMailNumber();
527 if (TextUtils.isEmpty(vmDisplay)) {
528 // if there is no voicemail number, we just return null to
529 // indicate no contribution.
530 return null;
531 }
532
533 // Return the voicemail number prepended with "VM: "
534 if (DBG) log("updating default for call forwarding dialogs");
535 return getString(R.string.voicemail_abbreviated) + " " + vmDisplay;
536 }
537
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700538 private void switchToPreviousVoicemailProvider() {
539 if (DBG) log("switchToPreviousVoicemailProvider " + mPreviousVMProviderKey);
540 if (mPreviousVMProviderKey != null) {
541 if (mVMChangeCompletedSuccessfully || mFwdChangesRequireRollback) {
542 // we have to revert with carrier
543 if (DBG) {
544 log("Needs to rollback."
545 + " mVMChangeCompletedSuccessfully=" + mVMChangeCompletedSuccessfully
546 + ", mFwdChangesRequireRollback=" + mFwdChangesRequireRollback);
547 }
548
549 showDialogIfForeground(VOICEMAIL_REVERTING_DIALOG);
Andrew Leeb490d732014-10-27 15:00:41 -0700550 final VoicemailProviderSettings prevSettings =
Andrew Lee88b51e22014-10-29 15:48:51 -0700551 mVmProviderSettingsUtil.load(mPreviousVMProviderKey);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700552 if (prevSettings == null) {
553 // prevSettings never becomes null since it should be already loaded!
Andrew Leeb490d732014-10-27 15:00:41 -0700554 Log.e(LOG_TAG, "VoicemailProviderSettings for the key \""
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700555 + mPreviousVMProviderKey + "\" becomes null, which is unexpected.");
556 if (DBG) {
557 Log.e(LOG_TAG,
558 "mVMChangeCompletedSuccessfully: " + mVMChangeCompletedSuccessfully
559 + ", mFwdChangesRequireRollback: " + mFwdChangesRequireRollback);
560 }
561 }
562 if (mVMChangeCompletedSuccessfully) {
Andrew Leeb490d732014-10-27 15:00:41 -0700563 mNewVMNumber = prevSettings.getVoicemailNumber();
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700564 Log.i(LOG_TAG, "VM change is already completed successfully."
565 + "Have to revert VM back to " + mNewVMNumber + " again.");
566 mPhone.setVoiceMailNumber(
567 mPhone.getVoiceMailAlphaTag().toString(),
568 mNewVMNumber,
569 Message.obtain(mRevertOptionComplete, EVENT_VOICEMAIL_CHANGED));
570 }
571 if (mFwdChangesRequireRollback) {
572 Log.i(LOG_TAG, "Requested to rollback Fwd changes.");
Andrew Leeb490d732014-10-27 15:00:41 -0700573 final CallForwardInfo[] prevFwdSettings = prevSettings.getForwardingSettings();
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700574 if (prevFwdSettings != null) {
575 Map<Integer, AsyncResult> results =
576 mForwardingChangeResults;
577 resetForwardingChangeState();
578 for (int i = 0; i < prevFwdSettings.length; i++) {
579 CallForwardInfo fi = prevFwdSettings[i];
580 if (DBG) log("Reverting fwd #: " + i + ": " + fi.toString());
581 // Only revert the settings for which the update
582 // succeeded
583 AsyncResult result = results.get(fi.reason);
584 if (result != null && result.exception == null) {
585 mExpectedChangeResultReasons.add(fi.reason);
586 mPhone.setCallForwardingOption(
587 (fi.status == 1 ?
588 CommandsInterface.CF_ACTION_REGISTRATION :
589 CommandsInterface.CF_ACTION_DISABLE),
590 fi.reason,
591 fi.number,
592 fi.timeSeconds,
593 mRevertOptionComplete.obtainMessage(
594 EVENT_FORWARDING_CHANGED, i, 0));
595 }
596 }
597 }
598 }
599 } else {
600 if (DBG) log("No need to revert");
601 onRevertDone();
602 }
603 }
604 }
605
606 private void onRevertDone() {
607 if (DBG) log("Flipping provider key back to " + mPreviousVMProviderKey);
608 mVoicemailProviders.setValue(mPreviousVMProviderKey);
609 updateVMPreferenceWidgets(mPreviousVMProviderKey);
610 updateVoiceNumberField();
611 if (mVMOrFwdSetError != 0) {
Andrew Leeab082272014-11-04 15:50:42 -0800612 showDialogIfForeground(mVMOrFwdSetError);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700613 mVMOrFwdSetError = 0;
614 }
615 }
616
617 @Override
618 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
619 if (DBG) {
620 log("onActivityResult: requestCode: " + requestCode
621 + ", resultCode: " + resultCode
622 + ", data: " + data);
623 }
624 // there are cases where the contact picker may end up sending us more than one
625 // request. We want to ignore the request if we're not in the correct state.
626 if (requestCode == VOICEMAIL_PROVIDER_CFG_ID) {
627 boolean failure = false;
628
629 // No matter how the processing of result goes lets clear the flag
630 if (DBG) log("mVMProviderSettingsForced: " + mVMProviderSettingsForced);
631 final boolean isVMProviderSettingsForced = mVMProviderSettingsForced;
632 mVMProviderSettingsForced = false;
633
634 String vmNum = null;
635 if (resultCode != RESULT_OK) {
636 if (DBG) log("onActivityResult: vm provider cfg result not OK.");
637 failure = true;
638 } else {
639 if (data == null) {
640 if (DBG) log("onActivityResult: vm provider cfg result has no data");
641 failure = true;
642 } else {
643 if (data.getBooleanExtra(SIGNOUT_EXTRA, false)) {
644 if (DBG) log("Provider requested signout");
645 if (isVMProviderSettingsForced) {
646 if (DBG) log("Going back to previous provider on signout");
647 switchToPreviousVoicemailProvider();
648 } else {
649 final String victim = getCurrentVoicemailProviderKey();
650 if (DBG) log("Relaunching activity and ignoring " + victim);
651 Intent i = new Intent(ACTION_ADD_VOICEMAIL);
652 i.putExtra(IGNORE_PROVIDER_EXTRA, victim);
653 i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
654 this.startActivity(i);
655 }
656 return;
657 }
658 vmNum = data.getStringExtra(VM_NUMBER_EXTRA);
659 if (vmNum == null || vmNum.length() == 0) {
660 if (DBG) log("onActivityResult: vm provider cfg result has no vmnum");
661 failure = true;
662 }
663 }
664 }
665 if (failure) {
666 if (DBG) log("Failure in return from voicemail provider");
667 if (isVMProviderSettingsForced) {
668 switchToPreviousVoicemailProvider();
669 } else {
670 if (DBG) log("Not switching back the provider since this is not forced config");
671 }
672 return;
673 }
674 mChangingVMorFwdDueToProviderChange = isVMProviderSettingsForced;
675 final String fwdNum = data.getStringExtra(FWD_NUMBER_EXTRA);
676
Santos Cordonda120f42014-08-06 04:44:34 -0700677 // TODO: It would be nice to load the current network setting for this and
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700678 // send it to the provider when it's config is invoked so it can use this as default
679 final int fwdNumTime = data.getIntExtra(FWD_NUMBER_TIME_EXTRA, 20);
680
681 if (DBG) log("onActivityResult: vm provider cfg result " +
682 (fwdNum != null ? "has" : " does not have") + " forwarding number");
683 saveVoiceMailAndForwardingNumber(getCurrentVoicemailProviderKey(),
Andrew Leeb490d732014-10-27 15:00:41 -0700684 new VoicemailProviderSettings(vmNum, fwdNum, fwdNumTime));
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700685 return;
686 }
687
688 if (requestCode == VOICEMAIL_PREF_ID) {
689 if (resultCode != RESULT_OK) {
690 if (DBG) log("onActivityResult: contact picker result not OK.");
691 return;
692 }
693
694 Cursor cursor = null;
695 try {
696 cursor = getContentResolver().query(data.getData(),
697 NUM_PROJECTION, null, null, null);
698 if ((cursor == null) || (!cursor.moveToFirst())) {
699 if (DBG) log("onActivityResult: bad contact data, no results found.");
700 return;
701 }
702 mSubMenuVoicemailSettings.onPickActivityResult(cursor.getString(0));
703 return;
704 } finally {
705 if (cursor != null) {
706 cursor.close();
707 }
708 }
709 }
710
711 super.onActivityResult(requestCode, resultCode, data);
712 }
713
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700714 /**
715 * Wrapper around showDialog() that will silently do nothing if we're
716 * not in the foreground.
717 *
718 * This is useful here because most of the dialogs we display from
719 * this class are triggered by asynchronous events (like
720 * success/failure messages from the telephony layer) and it's
721 * possible for those events to come in even after the user has gone
722 * to a different screen.
723 */
724 // TODO: this is too brittle: it's still easy to accidentally add new
725 // code here that calls showDialog() directly (which will result in a
726 // WindowManager$BadTokenException if called after the activity has
727 // been stopped.)
728 //
729 // It would be cleaner to do the "if (mForeground)" check in one
730 // central place, maybe by using a single Handler for all asynchronous
731 // events (and have *that* discard events if we're not in the
732 // foreground.)
733 //
734 // Unfortunately it's not that simple, since we sometimes need to do
735 // actual work to handle these events whether or not we're in the
736 // foreground (see the Handler code in mSetOptionComplete for
737 // example.)
Andrew Leeab082272014-11-04 15:50:42 -0800738 //
739 // TODO: It's a bit worrisome that we don't do anything in error cases when we're not in the
740 // foreground. Consider displaying a toast instead.
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700741 private void showDialogIfForeground(int id) {
742 if (mForeground) {
743 showDialog(id);
744 }
745 }
746
747 private void dismissDialogSafely(int id) {
748 try {
749 dismissDialog(id);
750 } catch (IllegalArgumentException e) {
751 // This is expected in the case where we were in the background
752 // at the time we would normally have shown the dialog, so we didn't
753 // show it.
754 }
755 }
756
Andrew Leeb490d732014-10-27 15:00:41 -0700757 private void saveVoiceMailAndForwardingNumber(
758 String key, VoicemailProviderSettings newSettings) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700759 if (DBG) log("saveVoiceMailAndForwardingNumber: " + newSettings.toString());
Andrew Leeb490d732014-10-27 15:00:41 -0700760 mNewVMNumber = newSettings.getVoicemailNumber();
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700761 // empty vm number == clearing the vm number ?
762 if (mNewVMNumber == null) {
763 mNewVMNumber = "";
764 }
765
Andrew Leeb490d732014-10-27 15:00:41 -0700766 mNewFwdSettings = newSettings.getForwardingSettings();
767 if (DBG) log("newFwdNumber "
768 + String.valueOf((mNewFwdSettings != null ? mNewFwdSettings.length : 0))
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700769 + " settings");
770
771 // No fwd settings on CDMA
772 if (mPhone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA) {
773 if (DBG) log("ignoring forwarding setting since this is CDMA phone");
Andrew Leeb490d732014-10-27 15:00:41 -0700774 mNewFwdSettings = VoicemailProviderSettings.NO_FORWARDING;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700775 }
776
Andrew Leee3c15212014-10-28 13:12:55 -0700777 // Throw a warning if the voicemail is the same and we did not change forwarding.
Andrew Leeb490d732014-10-27 15:00:41 -0700778 if (mNewVMNumber.equals(mOldVmNumber)
779 && mNewFwdSettings == VoicemailProviderSettings.NO_FORWARDING) {
Andrew Leeab082272014-11-04 15:50:42 -0800780 showDialogIfForeground(VM_NOCHANGE_ERROR);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700781 return;
782 }
783
Andrew Lee88b51e22014-10-29 15:48:51 -0700784 mVmProviderSettingsUtil.save(key, newSettings);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700785 mVMChangeCompletedSuccessfully = false;
786 mFwdChangesRequireRollback = false;
787 mVMOrFwdSetError = 0;
788 if (!key.equals(mPreviousVMProviderKey)) {
789 mReadingSettingsForDefaultProvider =
790 mPreviousVMProviderKey.equals(DEFAULT_VM_PROVIDER_KEY);
791 if (DBG) log("Reading current forwarding settings");
Andrew Leeb490d732014-10-27 15:00:41 -0700792 int numSettingsReasons = VoicemailProviderSettings.FORWARDING_SETTINGS_REASONS.length;
793 mForwardingReadResults = new CallForwardInfo[numSettingsReasons];
794 for (int i = 0; i < mForwardingReadResults.length; i++) {
795 mPhone.getCallForwardingOption(
796 VoicemailProviderSettings.FORWARDING_SETTINGS_REASONS[i],
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700797 mGetOptionComplete.obtainMessage(EVENT_FORWARDING_GET_COMPLETED, i, 0));
798 }
799 showDialogIfForeground(VOICEMAIL_FWD_READING_DIALOG);
800 } else {
801 saveVoiceMailAndForwardingNumberStage2();
802 }
803 }
804
805 private final Handler mGetOptionComplete = new Handler() {
806 @Override
807 public void handleMessage(Message msg) {
808 AsyncResult result = (AsyncResult) msg.obj;
809 switch (msg.what) {
810 case EVENT_FORWARDING_GET_COMPLETED:
811 handleForwardingSettingsReadResult(result, msg.arg1);
812 break;
813 }
814 }
815 };
816
817 private void handleForwardingSettingsReadResult(AsyncResult ar, int idx) {
818 if (DBG) Log.d(LOG_TAG, "handleForwardingSettingsReadResult: " + idx);
819 Throwable error = null;
820 if (ar.exception != null) {
821 if (DBG) Log.d(LOG_TAG, "FwdRead: ar.exception=" +
822 ar.exception.getMessage());
823 error = ar.exception;
824 }
825 if (ar.userObj instanceof Throwable) {
826 if (DBG) Log.d(LOG_TAG, "FwdRead: userObj=" +
827 ((Throwable)ar.userObj).getMessage());
828 error = (Throwable)ar.userObj;
829 }
830
831 // We may have already gotten an error and decided to ignore the other results.
832 if (mForwardingReadResults == null) {
833 if (DBG) Log.d(LOG_TAG, "ignoring fwd reading result: " + idx);
834 return;
835 }
836
837 // In case of error ignore other results, show an error dialog
838 if (error != null) {
839 if (DBG) Log.d(LOG_TAG, "Error discovered for fwd read : " + idx);
840 mForwardingReadResults = null;
841 dismissDialogSafely(VOICEMAIL_FWD_READING_DIALOG);
Andrew Leeab082272014-11-04 15:50:42 -0800842 showDialogIfForeground(FW_GET_RESPONSE_ERROR);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700843 return;
844 }
845
846 // Get the forwarding info
847 final CallForwardInfo cfInfoArray[] = (CallForwardInfo[]) ar.result;
848 CallForwardInfo fi = null;
849 for (int i = 0 ; i < cfInfoArray.length; i++) {
850 if ((cfInfoArray[i].serviceClass & CommandsInterface.SERVICE_CLASS_VOICE) != 0) {
851 fi = cfInfoArray[i];
852 break;
853 }
854 }
855 if (fi == null) {
856
857 // In case we go nothing it means we need this reason disabled
858 // so create a CallForwardInfo for capturing this
859 if (DBG) Log.d(LOG_TAG, "Creating default info for " + idx);
860 fi = new CallForwardInfo();
861 fi.status = 0;
Andrew Leeb490d732014-10-27 15:00:41 -0700862 fi.reason = VoicemailProviderSettings.FORWARDING_SETTINGS_REASONS[idx];
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700863 fi.serviceClass = CommandsInterface.SERVICE_CLASS_VOICE;
864 } else {
865 // if there is not a forwarding number, ensure the entry is set to "not active."
866 if (fi.number == null || fi.number.length() == 0) {
867 fi.status = 0;
868 }
869
870 if (DBG) Log.d(LOG_TAG, "Got " + fi.toString() + " for " + idx);
871 }
872 mForwardingReadResults[idx] = fi;
873
874 // Check if we got all the results already
875 boolean done = true;
876 for (int i = 0; i < mForwardingReadResults.length; i++) {
877 if (mForwardingReadResults[i] == null) {
878 done = false;
879 break;
880 }
881 }
882 if (done) {
883 if (DBG) Log.d(LOG_TAG, "Done receiving fwd info");
884 dismissDialogSafely(VOICEMAIL_FWD_READING_DIALOG);
885 if (mReadingSettingsForDefaultProvider) {
Andrew Lee88b51e22014-10-29 15:48:51 -0700886 mVmProviderSettingsUtil.save(DEFAULT_VM_PROVIDER_KEY,
887 new VoicemailProviderSettings(this.mOldVmNumber, mForwardingReadResults));
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700888 mReadingSettingsForDefaultProvider = false;
889 }
890 saveVoiceMailAndForwardingNumberStage2();
891 } else {
892 if (DBG) Log.d(LOG_TAG, "Not done receiving fwd info");
893 }
894 }
895
896 private CallForwardInfo infoForReason(CallForwardInfo[] infos, int reason) {
897 CallForwardInfo result = null;
898 if (null != infos) {
899 for (CallForwardInfo info : infos) {
900 if (info.reason == reason) {
901 result = info;
902 break;
903 }
904 }
905 }
906 return result;
907 }
908
Andrew Leee438b312014-10-29 16:59:15 -0700909 private boolean isUpdateRequired(CallForwardInfo oldInfo, CallForwardInfo newInfo) {
910 if (oldInfo == null) {
911 return true;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700912 }
Andrew Leee438b312014-10-29 16:59:15 -0700913
914 // If we're disabling a type of forwarding, don't make any change if it's already disabled.
915 if (newInfo.status == CALL_FORWARD_INFO_INACTIVE_STATUS
916 && oldInfo.status == CALL_FORWARD_INFO_INACTIVE_STATUS) {
917 return false;
918 }
919
920 return true;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700921 }
922
923 private void resetForwardingChangeState() {
924 mForwardingChangeResults = new HashMap<Integer, AsyncResult>();
925 mExpectedChangeResultReasons = new HashSet<Integer>();
926 }
927
928 // Called after we are done saving the previous forwarding settings if
929 // we needed.
930 private void saveVoiceMailAndForwardingNumberStage2() {
931 mForwardingChangeResults = null;
932 mVoicemailChangeResult = null;
Andrew Leeb490d732014-10-27 15:00:41 -0700933 if (mNewFwdSettings != VoicemailProviderSettings.NO_FORWARDING) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700934 resetForwardingChangeState();
935 for (int i = 0; i < mNewFwdSettings.length; i++) {
936 CallForwardInfo fi = mNewFwdSettings[i];
937
938 final boolean doUpdate = isUpdateRequired(infoForReason(
939 mForwardingReadResults, fi.reason), fi);
940
941 if (doUpdate) {
942 if (DBG) log("Setting fwd #: " + i + ": " + fi.toString());
943 mExpectedChangeResultReasons.add(i);
944
945 mPhone.setCallForwardingOption(
946 fi.status == 1 ?
947 CommandsInterface.CF_ACTION_REGISTRATION :
948 CommandsInterface.CF_ACTION_DISABLE,
949 fi.reason,
950 fi.number,
951 fi.timeSeconds,
952 mSetOptionComplete.obtainMessage(
953 EVENT_FORWARDING_CHANGED, fi.reason, 0));
954 }
955 }
956 showDialogIfForeground(VOICEMAIL_FWD_SAVING_DIALOG);
957 } else {
958 if (DBG) log("Not touching fwd #");
959 setVMNumberWithCarrier();
960 }
961 }
962
963 private void setVMNumberWithCarrier() {
964 if (DBG) log("save voicemail #: " + mNewVMNumber);
965 mPhone.setVoiceMailNumber(
966 mPhone.getVoiceMailAlphaTag().toString(),
967 mNewVMNumber,
968 Message.obtain(mSetOptionComplete, EVENT_VOICEMAIL_CHANGED));
969 }
970
971 /**
972 * Callback to handle option update completions
973 */
974 private final Handler mSetOptionComplete = new Handler() {
975 @Override
976 public void handleMessage(Message msg) {
977 AsyncResult result = (AsyncResult) msg.obj;
978 boolean done = false;
979 switch (msg.what) {
980 case EVENT_VOICEMAIL_CHANGED:
981 mVoicemailChangeResult = result;
Andrew Leee438b312014-10-29 16:59:15 -0700982 mVMChangeCompletedSuccessfully = isVmChangeSuccess();
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700983 done = true;
984 break;
985 case EVENT_FORWARDING_CHANGED:
986 mForwardingChangeResults.put(msg.arg1, result);
987 if (result.exception != null) {
988 Log.w(LOG_TAG, "Error in setting fwd# " + msg.arg1 + ": " +
989 result.exception.getMessage());
990 } else {
991 if (DBG) log("Success in setting fwd# " + msg.arg1);
992 }
Andrew Leee438b312014-10-29 16:59:15 -0700993 if (isForwardingCompleted()) {
994 if (isFwdChangeSuccess()) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700995 if (DBG) log("Overall fwd changes completed ok, starting vm change");
996 setVMNumberWithCarrier();
997 } else {
998 Log.w(LOG_TAG, "Overall fwd changes completed in failure. " +
999 "Check if we need to try rollback for some settings.");
1000 mFwdChangesRequireRollback = false;
1001 Iterator<Map.Entry<Integer,AsyncResult>> it =
1002 mForwardingChangeResults.entrySet().iterator();
1003 while (it.hasNext()) {
1004 Map.Entry<Integer,AsyncResult> entry = it.next();
1005 if (entry.getValue().exception == null) {
1006 // If at least one succeeded we have to revert
1007 Log.i(LOG_TAG, "Rollback will be required");
1008 mFwdChangesRequireRollback = true;
1009 break;
1010 }
1011 }
1012 if (!mFwdChangesRequireRollback) {
1013 Log.i(LOG_TAG, "No rollback needed.");
1014 }
1015 done = true;
1016 }
1017 }
1018 break;
1019 default:
1020 // TODO: should never reach this, may want to throw exception
1021 }
1022 if (done) {
1023 if (DBG) log("All VM provider related changes done");
1024 if (mForwardingChangeResults != null) {
1025 dismissDialogSafely(VOICEMAIL_FWD_SAVING_DIALOG);
1026 }
Andrew Leee438b312014-10-29 16:59:15 -07001027 handleSetVmOrFwdMessage();
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001028 }
1029 }
1030 };
1031
1032 /**
1033 * Callback to handle option revert completions
1034 */
1035 private final Handler mRevertOptionComplete = new Handler() {
1036 @Override
1037 public void handleMessage(Message msg) {
1038 AsyncResult result = (AsyncResult) msg.obj;
1039 switch (msg.what) {
1040 case EVENT_VOICEMAIL_CHANGED:
1041 mVoicemailChangeResult = result;
1042 if (DBG) log("VM revert complete msg");
1043 break;
1044 case EVENT_FORWARDING_CHANGED:
1045 mForwardingChangeResults.put(msg.arg1, result);
1046 if (result.exception != null) {
1047 if (DBG) log("Error in reverting fwd# " + msg.arg1 + ": " +
1048 result.exception.getMessage());
1049 } else {
1050 if (DBG) log("Success in reverting fwd# " + msg.arg1);
1051 }
1052 if (DBG) log("FWD revert complete msg ");
1053 break;
1054 default:
1055 // TODO: should never reach this, may want to throw exception
1056 }
1057 final boolean done =
1058 (!mVMChangeCompletedSuccessfully || mVoicemailChangeResult != null) &&
Andrew Leee438b312014-10-29 16:59:15 -07001059 (!mFwdChangesRequireRollback || isForwardingCompleted());
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001060 if (done) {
1061 if (DBG) log("All VM reverts done");
1062 dismissDialogSafely(VOICEMAIL_REVERTING_DIALOG);
1063 onRevertDone();
1064 }
1065 }
1066 };
1067
1068 /**
Andrew Leee438b312014-10-29 16:59:15 -07001069 * Return true if there is a change result for every reason for which we expect a result.
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001070 */
Andrew Leee438b312014-10-29 16:59:15 -07001071 private boolean isForwardingCompleted() {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001072 if (mForwardingChangeResults == null) {
Andrew Leee438b312014-10-29 16:59:15 -07001073 return true;
1074 }
1075
1076 for (Integer reason : mExpectedChangeResultReasons) {
1077 if (mForwardingChangeResults.get(reason) == null) {
1078 return false;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001079 }
1080 }
Andrew Leee438b312014-10-29 16:59:15 -07001081
1082 return true;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001083 }
Andrew Leee438b312014-10-29 16:59:15 -07001084
1085 private boolean isFwdChangeSuccess() {
1086 if (mForwardingChangeResults == null) {
1087 return true;
1088 }
1089
1090 for (AsyncResult result : mForwardingChangeResults.values()) {
1091 Throwable exception = result.exception;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001092 if (exception != null) {
Andrew Leee438b312014-10-29 16:59:15 -07001093 String msg = exception.getMessage();
1094 msg = (msg != null) ? msg : "";
1095 Log.w(LOG_TAG, "Failed to change forwarding setting. Reason: " + msg);
1096 return false;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001097 }
1098 }
Andrew Leee438b312014-10-29 16:59:15 -07001099 return true;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001100 }
1101
Andrew Leee438b312014-10-29 16:59:15 -07001102 private boolean isVmChangeSuccess() {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001103 if (mVoicemailChangeResult.exception != null) {
Andrew Leee438b312014-10-29 16:59:15 -07001104 String msg = mVoicemailChangeResult.exception.getMessage();
1105 msg = (msg != null) ? msg : "";
1106 Log.w(LOG_TAG, "Failed to change voicemail. Reason: " + msg);
1107 return false;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001108 }
Andrew Leee438b312014-10-29 16:59:15 -07001109
1110 if (DBG) log("VM change completed successfully.");
1111 return true;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001112 }
1113
Andrew Leee438b312014-10-29 16:59:15 -07001114 private void handleSetVmOrFwdMessage() {
1115 if (DBG) log("handleSetVMMessage: set VM request complete");
1116
1117 if (!isFwdChangeSuccess()) {
Andrew Leeab082272014-11-04 15:50:42 -08001118 handleVmOrFwdSetError(FW_SET_RESPONSE_ERROR);
Andrew Leee438b312014-10-29 16:59:15 -07001119 } else if (!isVmChangeSuccess()) {
Andrew Leeab082272014-11-04 15:50:42 -08001120 handleVmOrFwdSetError(VM_RESPONSE_ERROR);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001121 } else {
Andrew Leee438b312014-10-29 16:59:15 -07001122 if (DBG) log("change VM success!");
Andrew Leeab082272014-11-04 15:50:42 -08001123 handleVmAndFwdSetSuccess(VOICEMAIL_DIALOG_CONFIRM);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001124 }
1125 }
1126
1127 /**
1128 * Called when Voicemail Provider or its forwarding settings failed. Rolls back partly made
1129 * changes to those settings and show "failure" dialog.
1130 *
Andrew Leeab082272014-11-04 15:50:42 -08001131 * @param dialogId ID of the dialog to show for the specific error case. Either
1132 * {@link #FW_SET_RESPONSE_ERROR} or {@link #VM_RESPONSE_ERROR}
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001133 */
Andrew Leeab082272014-11-04 15:50:42 -08001134 private void handleVmOrFwdSetError(int dialogId) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001135 if (mChangingVMorFwdDueToProviderChange) {
Andrew Leeab082272014-11-04 15:50:42 -08001136 mVMOrFwdSetError = dialogId;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001137 mChangingVMorFwdDueToProviderChange = false;
1138 switchToPreviousVoicemailProvider();
1139 return;
1140 }
1141 mChangingVMorFwdDueToProviderChange = false;
Andrew Leeab082272014-11-04 15:50:42 -08001142 showDialogIfForeground(dialogId);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001143 updateVoiceNumberField();
1144 }
1145
1146 /**
1147 * Called when Voicemail Provider and its forwarding settings were successfully finished.
1148 * This updates a bunch of variables and show "success" dialog.
1149 */
Andrew Leeab082272014-11-04 15:50:42 -08001150 private void handleVmAndFwdSetSuccess(int dialogId) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001151 if (DBG) {
Andrew Leee438b312014-10-29 16:59:15 -07001152 log("handleVmAndFwdSetSuccess(). current voicemail provider key: "
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001153 + getCurrentVoicemailProviderKey());
1154 }
1155 mPreviousVMProviderKey = getCurrentVoicemailProviderKey();
1156 mChangingVMorFwdDueToProviderChange = false;
Andrew Leeab082272014-11-04 15:50:42 -08001157 showDialogIfForeground(dialogId);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001158 updateVoiceNumberField();
1159 }
1160
1161 /**
1162 * Update the voicemail number from what we've recorded on the sim.
1163 */
1164 private void updateVoiceNumberField() {
1165 if (DBG) {
1166 log("updateVoiceNumberField(). mSubMenuVoicemailSettings=" + mSubMenuVoicemailSettings);
1167 }
1168 if (mSubMenuVoicemailSettings == null) {
1169 return;
1170 }
1171
1172 mOldVmNumber = mPhone.getVoiceMailNumber();
1173 if (mOldVmNumber == null) {
1174 mOldVmNumber = "";
1175 }
1176 mSubMenuVoicemailSettings.setPhoneNumber(mOldVmNumber);
1177 final String summary = (mOldVmNumber.length() > 0) ? mOldVmNumber :
1178 getString(R.string.voicemail_number_not_set);
1179 mSubMenuVoicemailSettings.setSummary(summary);
1180 }
1181
1182 /*
1183 * Helper Methods for Activity class.
1184 * The initial query commands are split into two pieces now
1185 * for individual expansion. This combined with the ability
1186 * to cancel queries allows for a much better user experience,
1187 * and also ensures that the user only waits to update the
1188 * data that is relevant.
1189 */
1190
1191 @Override
1192 protected void onPrepareDialog(int id, Dialog dialog) {
1193 super.onPrepareDialog(id, dialog);
1194 mCurrentDialogId = id;
1195 }
1196
1197 // dialog creation method, called by showDialog()
1198 @Override
1199 protected Dialog onCreateDialog(int id) {
1200 if ((id == VM_RESPONSE_ERROR) || (id == VM_NOCHANGE_ERROR) ||
1201 (id == FW_SET_RESPONSE_ERROR) || (id == FW_GET_RESPONSE_ERROR) ||
1202 (id == VOICEMAIL_DIALOG_CONFIRM)) {
1203
1204 AlertDialog.Builder b = new AlertDialog.Builder(this);
1205
1206 int msgId;
1207 int titleId = R.string.error_updating_title;
1208 switch (id) {
1209 case VOICEMAIL_DIALOG_CONFIRM:
1210 msgId = R.string.vm_changed;
1211 titleId = R.string.voicemail;
1212 // Set Button 2
1213 b.setNegativeButton(R.string.close_dialog, this);
1214 break;
1215 case VM_NOCHANGE_ERROR:
1216 // even though this is technically an error,
1217 // keep the title friendly.
1218 msgId = R.string.no_change;
1219 titleId = R.string.voicemail;
1220 // Set Button 2
1221 b.setNegativeButton(R.string.close_dialog, this);
1222 break;
1223 case VM_RESPONSE_ERROR:
1224 msgId = R.string.vm_change_failed;
1225 // Set Button 1
1226 b.setPositiveButton(R.string.close_dialog, this);
1227 break;
1228 case FW_SET_RESPONSE_ERROR:
1229 msgId = R.string.fw_change_failed;
1230 // Set Button 1
1231 b.setPositiveButton(R.string.close_dialog, this);
1232 break;
1233 case FW_GET_RESPONSE_ERROR:
1234 msgId = R.string.fw_get_in_vm_failed;
1235 b.setPositiveButton(R.string.alert_dialog_yes, this);
1236 b.setNegativeButton(R.string.alert_dialog_no, this);
1237 break;
1238 default:
1239 msgId = R.string.exception_error;
1240 // Set Button 3, tells the activity that the error is
1241 // not recoverable on dialog exit.
1242 b.setNeutralButton(R.string.close_dialog, this);
1243 break;
1244 }
1245
1246 b.setTitle(getText(titleId));
1247 String message = getText(msgId).toString();
1248 b.setMessage(message);
1249 b.setCancelable(false);
1250 AlertDialog dialog = b.create();
1251
1252 // make the dialog more obvious by bluring the background.
1253 dialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
1254
1255 return dialog;
1256 } else if (id == VOICEMAIL_FWD_SAVING_DIALOG || id == VOICEMAIL_FWD_READING_DIALOG ||
1257 id == VOICEMAIL_REVERTING_DIALOG) {
1258 ProgressDialog dialog = new ProgressDialog(this);
1259 dialog.setTitle(getText(R.string.updating_title));
1260 dialog.setIndeterminate(true);
1261 dialog.setCancelable(false);
1262 dialog.setMessage(getText(
1263 id == VOICEMAIL_FWD_SAVING_DIALOG ? R.string.updating_settings :
1264 (id == VOICEMAIL_REVERTING_DIALOG ? R.string.reverting_settings :
1265 R.string.reading_settings)));
1266 return dialog;
1267 }
1268
1269
1270 return null;
1271 }
1272
1273 // This is a method implemented for DialogInterface.OnClickListener.
1274 // Used with the error dialog to close the app, voicemail dialog to just dismiss.
1275 // Close button is mapped to BUTTON_POSITIVE for the errors that close the activity,
1276 // while those that are mapped to BUTTON_NEUTRAL only move the preference focus.
1277 public void onClick(DialogInterface dialog, int which) {
1278 dialog.dismiss();
1279 switch (which){
1280 case DialogInterface.BUTTON_NEUTRAL:
1281 if (DBG) log("Neutral button");
1282 break;
1283 case DialogInterface.BUTTON_NEGATIVE:
1284 if (DBG) log("Negative button");
1285 if (mCurrentDialogId == FW_GET_RESPONSE_ERROR) {
1286 // We failed to get current forwarding settings and the user
1287 // does not wish to continue.
1288 switchToPreviousVoicemailProvider();
1289 }
1290 break;
1291 case DialogInterface.BUTTON_POSITIVE:
1292 if (DBG) log("Positive button");
1293 if (mCurrentDialogId == FW_GET_RESPONSE_ERROR) {
1294 // We failed to get current forwarding settings but the user
1295 // wishes to continue changing settings to the new vm provider
1296 saveVoiceMailAndForwardingNumberStage2();
1297 } else {
1298 finish();
1299 }
1300 return;
1301 default:
1302 // just let the dialog close and go back to the input
1303 }
1304 // In all dialogs, all buttons except BUTTON_POSITIVE lead to the end of user interaction
1305 // with settings UI. If we were called to explicitly configure voice mail then
1306 // we finish the settings activity here to come back to whatever the user was doing.
1307 if (getIntent().getAction().equals(ACTION_ADD_VOICEMAIL)) {
1308 finish();
1309 }
1310 }
1311
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001312 /*
1313 * Activity class methods
1314 */
1315
1316 @Override
1317 protected void onCreate(Bundle icicle) {
1318 super.onCreate(icicle);
1319 if (DBG) log("onCreate(). Intent: " + getIntent());
1320 mPhone = PhoneGlobals.getPhone();
Tyler Gunnbaee2952014-09-10 16:01:02 -07001321 mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
Andrew Lee88b51e22014-10-29 15:48:51 -07001322 mVmProviderSettingsUtil = new VoicemailProviderSettingsUtil(getApplicationContext());
Tyler Gunnbaee2952014-09-10 16:01:02 -07001323
Tyler Gunnbaee2952014-09-10 16:01:02 -07001324 // Show the voicemail preference in onResume if the calling intent specifies the
1325 // ACTION_ADD_VOICEMAIL action.
1326 mShowVoicemailPreference = (icicle == null) &&
1327 getIntent().getAction().equals(ACTION_ADD_VOICEMAIL);
1328 }
1329
1330 private void initPhoneAccountPreferences() {
Andrew Leece8ae2a2014-09-10 10:41:48 -07001331 mPhoneAccountSettingsPreference = findPreference(PHONE_ACCOUNT_SETTINGS_KEY);
Tyler Gunnbaee2952014-09-10 16:01:02 -07001332
Tyler Gunn4d45d1c2014-09-12 22:17:53 -07001333 TelecomManager telecomManager = TelecomManager.from(this);
Andrew Lee93c345f2014-10-27 15:25:07 -07001334 TelephonyManager telephonyManager =
1335 (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
Tyler Gunnbaee2952014-09-10 16:01:02 -07001336
Andrew Lee93c345f2014-10-27 15:25:07 -07001337 if ((telecomManager.getSimCallManagers().isEmpty() && !SipUtil.isVoipSupported(this))
1338 || telephonyManager.getPhoneCount() > 1) {
Andrew Leece8ae2a2014-09-10 10:41:48 -07001339 getPreferenceScreen().removePreference(mPhoneAccountSettingsPreference);
Tyler Gunnbaee2952014-09-10 16:01:02 -07001340 }
1341 }
1342
1343 private boolean canLaunchIntent(Intent intent) {
1344 PackageManager pm = getPackageManager();
1345 return pm.resolveActivity(intent, PackageManager.GET_ACTIVITIES) != null;
1346 }
1347
Tyler Gunnbaee2952014-09-10 16:01:02 -07001348 @Override
1349 protected void onResume() {
1350 super.onResume();
1351 mForeground = true;
1352
1353 PreferenceScreen preferenceScreen = getPreferenceScreen();
1354 if (preferenceScreen != null) {
1355 preferenceScreen.removeAll();
1356 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001357
1358 addPreferencesFromResource(R.xml.call_feature_setting);
Andrew Leedb2fe562014-09-03 15:40:43 -07001359 initPhoneAccountPreferences();
1360
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001361 PreferenceScreen prefSet = getPreferenceScreen();
Andrew Lee64a7d792014-10-15 17:38:38 -07001362 mSubMenuVoicemailSettings = (EditPhoneNumberPreference) findPreference(BUTTON_VOICEMAIL_KEY);
1363 mSubMenuVoicemailSettings.setParentActivity(this, VOICEMAIL_PREF_ID, this);
1364 mSubMenuVoicemailSettings.setDialogOnClosedListener(this);
1365 mSubMenuVoicemailSettings.setDialogTitle(R.string.voicemail_settings_number_label);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001366
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001367 mButtonDTMF = (ListPreference) findPreference(BUTTON_DTMF_KEY);
1368 mButtonAutoRetry = (CheckBoxPreference) findPreference(BUTTON_RETRY_KEY);
1369 mButtonHAC = (CheckBoxPreference) findPreference(BUTTON_HAC_KEY);
1370 mButtonTTY = (ListPreference) findPreference(BUTTON_TTY_KEY);
1371 mVoicemailProviders = (ListPreference) findPreference(BUTTON_VOICEMAIL_PROVIDER_KEY);
Andrew Lee312e8172014-10-23 17:01:36 -07001372 mEnableVideoCalling = (CheckBoxPreference) findPreference(ENABLE_VIDEO_CALLING_KEY);
Andrew Lee2170a972014-08-13 18:13:01 -07001373
Andrew Lee2c027892014-10-29 11:29:54 -07001374 mVoicemailProviders.setOnPreferenceChangeListener(this);
1375 mVoicemailSettingsScreen =
1376 (PreferenceScreen) findPreference(VOICEMAIL_SETTING_SCREEN_PREF_KEY);
1377 mVoicemailSettings = (PreferenceScreen)findPreference(BUTTON_VOICEMAIL_SETTING_KEY);
1378 mVoicemailNotificationVibrate =
1379 (CheckBoxPreference) findPreference(BUTTON_VOICEMAIL_NOTIFICATION_VIBRATE_KEY);
1380 initVoiceMailProviders();
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001381
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001382
Andrew Lee64a7d792014-10-15 17:38:38 -07001383 if (getResources().getBoolean(R.bool.dtmf_type_enabled)) {
1384 mButtonDTMF.setOnPreferenceChangeListener(this);
1385 int dtmf = Settings.System.getInt(getContentResolver(),
1386 Settings.System.DTMF_TONE_TYPE_WHEN_DIALING, Constants.DTMF_TONE_TYPE_NORMAL);
1387 mButtonDTMF.setValueIndex(dtmf);
1388 } else {
1389 prefSet.removePreference(mButtonDTMF);
1390 mButtonDTMF = null;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001391 }
1392
Andrew Lee64a7d792014-10-15 17:38:38 -07001393 if (getResources().getBoolean(R.bool.auto_retry_enabled)) {
1394 mButtonAutoRetry.setOnPreferenceChangeListener(this);
1395 int autoretry = Settings.Global.getInt(
1396 getContentResolver(), Settings.Global.CALL_AUTO_RETRY, 0);
1397 mButtonAutoRetry.setChecked(autoretry != 0);
1398 } else {
1399 prefSet.removePreference(mButtonAutoRetry);
1400 mButtonAutoRetry = null;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001401 }
1402
Andrew Lee64a7d792014-10-15 17:38:38 -07001403 if (getResources().getBoolean(R.bool.hac_enabled)) {
1404 mButtonHAC.setOnPreferenceChangeListener(this);
1405 int hac = Settings.System.getInt(getContentResolver(), Settings.System.HEARING_AID, 0);
1406 mButtonHAC.setChecked(hac != 0);
1407 } else {
1408 prefSet.removePreference(mButtonHAC);
1409 mButtonHAC = null;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001410 }
1411
Andrew Lee64a7d792014-10-15 17:38:38 -07001412 TelecomManager telecomManager = TelecomManager.from(this);
1413 if (telecomManager != null && telecomManager.isTtySupported()) {
1414 mButtonTTY.setOnPreferenceChangeListener(this);
1415 int settingsTtyMode = Settings.Secure.getInt(getContentResolver(),
1416 Settings.Secure.PREFERRED_TTY_MODE,
1417 TelecomManager.TTY_MODE_OFF);
1418 mButtonTTY.setValue(Integer.toString(settingsTtyMode));
1419 updatePreferredTtyModeSummary(settingsTtyMode);
1420 } else {
1421 prefSet.removePreference(mButtonTTY);
1422 mButtonTTY = null;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001423 }
1424
1425 if (!getResources().getBoolean(R.bool.world_phone)) {
1426 Preference options = prefSet.findPreference(BUTTON_CDMA_OPTIONS);
Andrew Lee2170a972014-08-13 18:13:01 -07001427 if (options != null) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001428 prefSet.removePreference(options);
Andrew Lee2170a972014-08-13 18:13:01 -07001429 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001430 options = prefSet.findPreference(BUTTON_GSM_UMTS_OPTIONS);
Andrew Lee2170a972014-08-13 18:13:01 -07001431 if (options != null) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001432 prefSet.removePreference(options);
Andrew Lee2170a972014-08-13 18:13:01 -07001433 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001434
1435 int phoneType = mPhone.getPhoneType();
1436 if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) {
1437 Preference fdnButton = prefSet.findPreference(BUTTON_FDN_KEY);
Andrew Lee2170a972014-08-13 18:13:01 -07001438 if (fdnButton != null) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001439 prefSet.removePreference(fdnButton);
Andrew Lee2170a972014-08-13 18:13:01 -07001440 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001441 if (!getResources().getBoolean(R.bool.config_voice_privacy_disable)) {
1442 addPreferencesFromResource(R.xml.cdma_call_privacy);
1443 }
1444 } else if (phoneType == PhoneConstants.PHONE_TYPE_GSM) {
Andrew Lee2170a972014-08-13 18:13:01 -07001445 if (getResources().getBoolean(R.bool.config_additional_call_setting)) {
Etan Cohen0ca1c802014-07-07 15:35:48 -07001446 addPreferencesFromResource(R.xml.gsm_umts_call_options);
1447 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001448 } else {
1449 throw new IllegalStateException("Unexpected phone type: " + phoneType);
1450 }
1451 }
1452
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001453 // check the intent that started this activity and pop up the voicemail
1454 // dialog if we've been asked to.
1455 // If we have at least one non default VM provider registered then bring up
1456 // the selection for the VM provider, otherwise bring up a VM number dialog.
1457 // We only bring up the dialog the first time we are called (not after orientation change)
Andrew Lee2c027892014-10-29 11:29:54 -07001458 if (mShowVoicemailPreference) {
Tyler Gunnbaee2952014-09-10 16:01:02 -07001459 if (DBG) {
1460 log("ACTION_ADD_VOICEMAIL Intent is thrown. current VM data size: "
1461 + mVMProvidersData.size());
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001462 }
Tyler Gunnbaee2952014-09-10 16:01:02 -07001463 if (mVMProvidersData.size() > 1) {
1464 simulatePreferenceClick(mVoicemailProviders);
1465 } else {
1466 onPreferenceChange(mVoicemailProviders, DEFAULT_VM_PROVIDER_KEY);
1467 mVoicemailProviders.setValue(DEFAULT_VM_PROVIDER_KEY);
1468 }
1469 mShowVoicemailPreference = false;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001470 }
Tyler Gunnbaee2952014-09-10 16:01:02 -07001471
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001472 updateVoiceNumberField();
1473 mVMProviderSettingsForced = false;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001474
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001475 SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(
1476 mPhone.getContext());
1477 if (migrateVoicemailVibrationSettingsIfNeeded(prefs)) {
1478 mVoicemailNotificationVibrate.setChecked(prefs.getBoolean(
1479 BUTTON_VOICEMAIL_NOTIFICATION_VIBRATE_KEY, false));
1480 }
1481
Andrew Lee312e8172014-10-23 17:01:36 -07001482 if (ImsManager.isVtEnabledByPlatform(mPhone.getContext()) && ENABLE_VT_FLAG) {
1483 boolean currentValue =
1484 ImsManager.isEnhanced4gLteModeSettingEnabledByUser(mPhone.getContext())
1485 ? PhoneGlobals.getInstance().phoneMgr.isVideoCallingEnabled() : false;
1486 mEnableVideoCalling.setChecked(currentValue);
Andrew Lee77527ac2014-10-21 16:57:39 -07001487 mEnableVideoCalling.setOnPreferenceChangeListener(this);
1488 } else {
1489 prefSet.removePreference(mEnableVideoCalling);
1490 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001491 }
1492
1493 // Migrate settings from BUTTON_VOICEMAIL_NOTIFICATION_VIBRATE_WHEN_KEY to
1494 // BUTTON_VOICEMAIL_NOTIFICATION_VIBRATE_KEY, if the latter does not exist.
1495 // Returns true if migration was performed.
1496 public static boolean migrateVoicemailVibrationSettingsIfNeeded(SharedPreferences prefs) {
1497 if (!prefs.contains(BUTTON_VOICEMAIL_NOTIFICATION_VIBRATE_KEY)) {
1498 String vibrateWhen = prefs.getString(
1499 BUTTON_VOICEMAIL_NOTIFICATION_VIBRATE_WHEN_KEY, VOICEMAIL_VIBRATION_NEVER);
1500 // If vibrateWhen is always, then voicemailVibrate should be True.
1501 // otherwise if vibrateWhen is "only in silent mode", or "never", then
1502 // voicemailVibrate = False.
1503 boolean voicemailVibrate = vibrateWhen.equals(VOICEMAIL_VIBRATION_ALWAYS);
1504 final SharedPreferences.Editor editor = prefs.edit();
1505 editor.putBoolean(BUTTON_VOICEMAIL_NOTIFICATION_VIBRATE_KEY, voicemailVibrate);
1506 editor.commit();
1507 return true;
1508 }
1509 return false;
1510 }
1511
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001512 private void handleTTYChange(Preference preference, Object objValue) {
1513 int buttonTtyMode;
1514 buttonTtyMode = Integer.valueOf((String) objValue).intValue();
1515 int settingsTtyMode = android.provider.Settings.Secure.getInt(
1516 getContentResolver(),
Sailesh Nepalbf900542014-07-15 16:18:32 -07001517 android.provider.Settings.Secure.PREFERRED_TTY_MODE,
Tyler Gunn4d45d1c2014-09-12 22:17:53 -07001518 TelecomManager.TTY_MODE_OFF);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001519 if (DBG) log("handleTTYChange: requesting set TTY mode enable (TTY) to" +
1520 Integer.toString(buttonTtyMode));
1521
1522 if (buttonTtyMode != settingsTtyMode) {
1523 switch(buttonTtyMode) {
Tyler Gunn4d45d1c2014-09-12 22:17:53 -07001524 case TelecomManager.TTY_MODE_OFF:
1525 case TelecomManager.TTY_MODE_FULL:
1526 case TelecomManager.TTY_MODE_HCO:
1527 case TelecomManager.TTY_MODE_VCO:
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001528 android.provider.Settings.Secure.putInt(getContentResolver(),
1529 android.provider.Settings.Secure.PREFERRED_TTY_MODE, buttonTtyMode);
1530 break;
1531 default:
Tyler Gunn4d45d1c2014-09-12 22:17:53 -07001532 buttonTtyMode = TelecomManager.TTY_MODE_OFF;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001533 }
1534
1535 mButtonTTY.setValue(Integer.toString(buttonTtyMode));
1536 updatePreferredTtyModeSummary(buttonTtyMode);
Tyler Gunn4d45d1c2014-09-12 22:17:53 -07001537 Intent ttyModeChanged = new Intent(TelecomManager.ACTION_TTY_PREFERRED_MODE_CHANGED);
1538 ttyModeChanged.putExtra(TelecomManager.EXTRA_TTY_PREFERRED_MODE, buttonTtyMode);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001539 sendBroadcastAsUser(ttyModeChanged, UserHandle.ALL);
1540 }
1541 }
1542
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001543 private void updatePreferredTtyModeSummary(int TtyMode) {
1544 String [] txts = getResources().getStringArray(R.array.tty_mode_entries);
1545 switch(TtyMode) {
Tyler Gunn4d45d1c2014-09-12 22:17:53 -07001546 case TelecomManager.TTY_MODE_OFF:
1547 case TelecomManager.TTY_MODE_HCO:
1548 case TelecomManager.TTY_MODE_VCO:
1549 case TelecomManager.TTY_MODE_FULL:
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001550 mButtonTTY.setSummary(txts[TtyMode]);
1551 break;
1552 default:
1553 mButtonTTY.setEnabled(false);
Tyler Gunn4d45d1c2014-09-12 22:17:53 -07001554 mButtonTTY.setSummary(txts[TelecomManager.TTY_MODE_OFF]);
Sailesh Nepalbf900542014-07-15 16:18:32 -07001555 break;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001556 }
1557 }
1558
1559 private static void log(String msg) {
1560 Log.d(LOG_TAG, msg);
1561 }
1562
1563 /**
1564 * Updates the look of the VM preference widgets based on current VM provider settings.
1565 * Note that the provider name is loaded form the found activity via loadLabel in
1566 * {@link #initVoiceMailProviders()} in order for it to be localizable.
1567 */
1568 private void updateVMPreferenceWidgets(String currentProviderSetting) {
1569 final String key = currentProviderSetting;
1570 final VoiceMailProvider provider = mVMProvidersData.get(key);
1571
1572 /* This is the case when we are coming up on a freshly wiped phone and there is no
1573 persisted value for the list preference mVoicemailProviders.
1574 In this case we want to show the UI asking the user to select a voicemail provider as
1575 opposed to silently falling back to default one. */
1576 if (provider == null) {
1577 if (DBG) {
1578 log("updateVMPreferenceWidget: provider for the key \"" + key + "\" is null.");
1579 }
1580 mVoicemailProviders.setSummary(getString(R.string.sum_voicemail_choose_provider));
1581 mVoicemailSettings.setEnabled(false);
1582 mVoicemailSettings.setIntent(null);
1583
1584 mVoicemailNotificationVibrate.setEnabled(false);
1585 } else {
1586 if (DBG) {
1587 log("updateVMPreferenceWidget: provider for the key \"" + key + "\".."
1588 + "name: " + provider.name
1589 + ", intent: " + provider.intent);
1590 }
1591 final String providerName = provider.name;
1592 mVoicemailProviders.setSummary(providerName);
1593 mVoicemailSettings.setEnabled(true);
1594 mVoicemailSettings.setIntent(provider.intent);
1595
1596 mVoicemailNotificationVibrate.setEnabled(true);
1597 }
1598 }
1599
1600 /**
1601 * Enumerates existing VM providers and puts their data into the list and populates
1602 * the preference list objects with their names.
1603 * In case we are called with ACTION_ADD_VOICEMAIL intent the intent may have
1604 * an extra string called IGNORE_PROVIDER_EXTRA with "package.activityName" of the provider
1605 * which should be hidden when we bring up the list of possible VM providers to choose.
1606 */
1607 private void initVoiceMailProviders() {
1608 if (DBG) log("initVoiceMailProviders()");
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001609
1610 String providerToIgnore = null;
Andrew Leef1776d82014-11-04 14:45:02 -08001611 if (getIntent().getAction().equals(ACTION_ADD_VOICEMAIL)
1612 && getIntent().hasExtra(IGNORE_PROVIDER_EXTRA)) {
1613 providerToIgnore = getIntent().getStringExtra(IGNORE_PROVIDER_EXTRA);
1614 // Remove this provider from the list.
1615 if (!TextUtils.isEmpty(providerToIgnore)) {
1616 if (DBG) log("Found ACTION_ADD_VOICEMAIL. providerToIgnore= " + providerToIgnore);
Andrew Lee88b51e22014-10-29 15:48:51 -07001617 mVmProviderSettingsUtil.delete(providerToIgnore);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001618 }
1619 }
1620
1621 mVMProvidersData.clear();
1622
Andrew Leef1776d82014-11-04 14:45:02 -08001623 List<String> entries = new ArrayList<String>();
1624 List<String> values = new ArrayList<String>();
1625
1626 // Add default voicemail provider.
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001627 final String myCarrier = getString(R.string.voicemail_default);
1628 mVMProvidersData.put(DEFAULT_VM_PROVIDER_KEY, new VoiceMailProvider(myCarrier, null));
Andrew Leef1776d82014-11-04 14:45:02 -08001629 entries.add(myCarrier);
1630 values.add(DEFAULT_VM_PROVIDER_KEY);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001631
Andrew Leef1776d82014-11-04 14:45:02 -08001632 // Add other voicemail providers.
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001633 PackageManager pm = getPackageManager();
Andrew Leef1776d82014-11-04 14:45:02 -08001634 Intent intent = new Intent(ACTION_CONFIGURE_VOICEMAIL);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001635 List<ResolveInfo> resolveInfos = pm.queryIntentActivities(intent, 0);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001636 for (int i = 0; i < resolveInfos.size(); i++) {
1637 final ResolveInfo ri= resolveInfos.get(i);
1638 final ActivityInfo currentActivityInfo = ri.activityInfo;
Andrew Lee6214e2b2014-11-04 13:57:38 -08001639 final String key = currentActivityInfo.name;
Andrew Leef1776d82014-11-04 14:45:02 -08001640
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001641 if (key.equals(providerToIgnore)) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001642 continue;
1643 }
Andrew Leef1776d82014-11-04 14:45:02 -08001644
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001645 if (DBG) log("Loading key: " + key);
1646 final String nameForDisplay = ri.loadLabel(pm).toString();
1647 Intent providerIntent = new Intent();
1648 providerIntent.setAction(ACTION_CONFIGURE_VOICEMAIL);
Andrew Leef1776d82014-11-04 14:45:02 -08001649 providerIntent.setClassName(currentActivityInfo.packageName, currentActivityInfo.name);
1650 VoiceMailProvider vmProvider = new VoiceMailProvider(nameForDisplay, providerIntent);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001651
Andrew Leef1776d82014-11-04 14:45:02 -08001652 if (DBG) log("Store VoiceMailProvider. Key: " + key + " -> " + vmProvider.toString());
1653 mVMProvidersData.put(key, vmProvider);
1654 entries.add(vmProvider.name);
1655 values.add(key);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001656 }
1657
Andrew Leef1776d82014-11-04 14:45:02 -08001658 mVoicemailProviders.setEntries(entries.toArray(new String[0]));
1659 mVoicemailProviders.setEntryValues(values.toArray(new String[0]));
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001660
Andrew Leef1776d82014-11-04 14:45:02 -08001661 // Remember the current Voicemail Provider key as a "previous" key. This will be used when
1662 // we fail to update Voicemail Provider, which requires rollback. We will update this when
1663 // the VM Provider setting is successfully updated.
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001664 mPreviousVMProviderKey = getCurrentVoicemailProviderKey();
1665 if (DBG) log("Set up the first mPreviousVMProviderKey: " + mPreviousVMProviderKey);
1666
1667 // Finally update the preference texts.
1668 updateVMPreferenceWidgets(mPreviousVMProviderKey);
1669 }
1670
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001671 /**
1672 * Simulates user clicking on a passed preference.
1673 * Usually needed when the preference is a dialog preference and we want to invoke
1674 * a dialog for this preference programmatically.
Santos Cordonda120f42014-08-06 04:44:34 -07001675 * TODO: figure out if there is a cleaner way to cause preference dlg to come up
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001676 */
1677 private void simulatePreferenceClick(Preference preference) {
1678 // Go through settings until we find our setting
1679 // and then simulate a click on it to bring up the dialog
1680 final ListAdapter adapter = getPreferenceScreen().getRootAdapter();
1681 for (int idx = 0; idx < adapter.getCount(); idx++) {
1682 if (adapter.getItem(idx) == preference) {
1683 getPreferenceScreen().onItemClick(this.getListView(),
1684 null, idx, adapter.getItemId(idx));
1685 break;
1686 }
1687 }
1688 }
1689
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001690 private String getCurrentVoicemailProviderKey() {
1691 final String key = mVoicemailProviders.getValue();
1692 return (key != null) ? key : DEFAULT_VM_PROVIDER_KEY;
1693 }
1694
1695 @Override
1696 public boolean onOptionsItemSelected(MenuItem item) {
1697 final int itemId = item.getItemId();
1698 if (itemId == android.R.id.home) { // See ActionBar#setDisplayHomeAsUpEnabled()
Yorke Leef2d0cac2013-09-09 19:42:56 -07001699 onBackPressed();
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001700 return true;
1701 }
1702 return super.onOptionsItemSelected(item);
1703 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001704 /**
1705 * Finish current Activity and go up to the top level Settings ({@link CallFeaturesSetting}).
1706 * This is useful for implementing "HomeAsUp" capability for second-level Settings.
1707 */
1708 public static void goUpToTopLevelSetting(Activity activity) {
1709 Intent intent = new Intent(activity, CallFeaturesSetting.class);
1710 intent.setAction(Intent.ACTION_MAIN);
1711 intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
1712 activity.startActivity(intent);
1713 activity.finish();
1714 }
1715}