blob: 5c1152196d4f29c6c44798db57c426437b2e9e6e [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;
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;
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";
118 // Extra put in the return from VM provider config containing voicemail number to set
119 public static final String VM_NUMBER_EXTRA = "com.android.phone.VoicemailNumber";
120 // Extra put in the return from VM provider config containing call forwarding number to set
121 public static final String FWD_NUMBER_EXTRA = "com.android.phone.ForwardingNumber";
122 // Extra put in the return from VM provider config containing call forwarding number to set
123 public static final String FWD_NUMBER_TIME_EXTRA = "com.android.phone.ForwardingNumberTime";
124 // If the VM provider returns non null value in this extra we will force the user to
125 // choose another VM provider
126 public static final String SIGNOUT_EXTRA = "com.android.phone.Signout";
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700127
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700128 // Key identifying the default vocie mail provider
129 public static final String DEFAULT_VM_PROVIDER_KEY = "";
130
131 /**
132 * String Extra put into ACTION_ADD_VOICEMAIL call to indicate which provider should be hidden
133 * in the list of providers presented to the user. This allows a provider which is being
134 * disabled (e.g. GV user logging out) to force the user to pick some other provider.
135 */
136 public static final String IGNORE_PROVIDER_EXTRA = "com.android.phone.ProviderToIgnore";
137
138 // string constants
139 private static final String NUM_PROJECTION[] = {CommonDataKinds.Phone.NUMBER};
140
141 // String keys for preference lookup
142 // TODO: Naming these "BUTTON_*" is confusing since they're not actually buttons(!)
Andrew Lee97708a42014-09-25 12:39:07 -0700143 private static final String VOICEMAIL_SETTING_SCREEN_PREF_KEY = "button_voicemail_category_key";
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700144 private static final String BUTTON_VOICEMAIL_KEY = "button_voicemail_key";
145 private static final String BUTTON_VOICEMAIL_PROVIDER_KEY = "button_voicemail_provider_key";
146 private static final String BUTTON_VOICEMAIL_SETTING_KEY = "button_voicemail_setting_key";
147 // New preference key for voicemail notification vibration
148 /* package */ static final String BUTTON_VOICEMAIL_NOTIFICATION_VIBRATE_KEY =
149 "button_voicemail_notification_vibrate_key";
150 // Old preference key for voicemail notification vibration. Used for migration to the new
151 // preference key only.
152 /* package */ static final String BUTTON_VOICEMAIL_NOTIFICATION_VIBRATE_WHEN_KEY =
153 "button_voicemail_notification_vibrate_when_key";
154 /* package */ static final String BUTTON_VOICEMAIL_NOTIFICATION_RINGTONE_KEY =
155 "button_voicemail_notification_ringtone_key";
156 private static final String BUTTON_FDN_KEY = "button_fdn_key";
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700157
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700158 private static final String BUTTON_DTMF_KEY = "button_dtmf_settings";
159 private static final String BUTTON_RETRY_KEY = "button_auto_retry_key";
160 private static final String BUTTON_TTY_KEY = "button_tty_mode_key";
161 private static final String BUTTON_HAC_KEY = "button_hac_key";
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700162
163 private static final String BUTTON_GSM_UMTS_OPTIONS = "button_gsm_more_expand_key";
164 private static final String BUTTON_CDMA_OPTIONS = "button_cdma_more_expand_key";
165
Andrew Leedb2fe562014-09-03 15:40:43 -0700166 private static final String DEFAULT_OUTGOING_ACCOUNT_KEY = "default_outgoing_account";
Andrew Leece8ae2a2014-09-10 10:41:48 -0700167 private static final String PHONE_ACCOUNT_SETTINGS_KEY =
168 "phone_account_settings_preference_screen";
Andrew Leedb2fe562014-09-03 15:40:43 -0700169
Andrew Leedf14ead2014-10-17 14:22:52 -0700170 private static final String ENABLE_VIDEO_CALLING_KEY = "button_enable_video_calling";
171
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700172 /** Event for Async voicemail change call */
173 private static final int EVENT_VOICEMAIL_CHANGED = 500;
174 private static final int EVENT_FORWARDING_CHANGED = 501;
175 private static final int EVENT_FORWARDING_GET_COMPLETED = 502;
176
Andrew Lee2170a972014-08-13 18:13:01 -0700177 private static final int MSG_UPDATE_VOICEMAIL_RINGTONE_SUMMARY = 1;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700178
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700179 public static final String HAC_KEY = "HACSetting";
180 public static final String HAC_VAL_ON = "ON";
181 public static final String HAC_VAL_OFF = "OFF";
182
183 /** Handle to voicemail pref */
184 private static final int VOICEMAIL_PREF_ID = 1;
185 private static final int VOICEMAIL_PROVIDER_CFG_ID = 2;
186
187 private Phone mPhone;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700188 private AudioManager mAudioManager;
Andrew Lee88b51e22014-10-29 15:48:51 -0700189 private VoicemailProviderSettingsUtil mVmProviderSettingsUtil;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700190
191 private static final int VM_NOCHANGE_ERROR = 400;
192 private static final int VM_RESPONSE_ERROR = 500;
193 private static final int FW_SET_RESPONSE_ERROR = 501;
194 private static final int FW_GET_RESPONSE_ERROR = 502;
195
196
197 // dialog identifiers for voicemail
198 private static final int VOICEMAIL_DIALOG_CONFIRM = 600;
199 private static final int VOICEMAIL_FWD_SAVING_DIALOG = 601;
200 private static final int VOICEMAIL_FWD_READING_DIALOG = 602;
201 private static final int VOICEMAIL_REVERTING_DIALOG = 603;
202
Andrew Leee438b312014-10-29 16:59:15 -0700203 /**
204 * @see CallForwardInfo#status
205 */
206 private static final int CALL_FORWARD_INFO_INACTIVE_STATUS = 0;
207
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700208 // voicemail notification vibration string constants
209 private static final String VOICEMAIL_VIBRATION_ALWAYS = "always";
210 private static final String VOICEMAIL_VIBRATION_NEVER = "never";
211
Andrew Lee5ed870c2014-10-29 11:47:49 -0700212 private SubscriptionInfoHelper mSubscriptionInfoHelper;
213
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700214 private EditPhoneNumberPreference mSubMenuVoicemailSettings;
215
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700216 /** Whether dialpad plays DTMF tone or not. */
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700217 private CheckBoxPreference mButtonAutoRetry;
218 private CheckBoxPreference mButtonHAC;
219 private ListPreference mButtonDTMF;
220 private ListPreference mButtonTTY;
Andrew Leece8ae2a2014-09-10 10:41:48 -0700221 private Preference mPhoneAccountSettingsPreference;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700222 private ListPreference mVoicemailProviders;
Andrew Lee97708a42014-09-25 12:39:07 -0700223 private PreferenceScreen mVoicemailSettingsScreen;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700224 private PreferenceScreen mVoicemailSettings;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700225 private CheckBoxPreference mVoicemailNotificationVibrate;
Andrew Leedf14ead2014-10-17 14:22:52 -0700226 private CheckBoxPreference mEnableVideoCalling;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700227
228 private class VoiceMailProvider {
229 public VoiceMailProvider(String name, Intent intent) {
230 this.name = name;
231 this.intent = intent;
232 }
233 public String name;
234 public Intent intent;
235 }
236
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700237 /**
238 * Results of reading forwarding settings
239 */
240 private CallForwardInfo[] mForwardingReadResults = null;
241
242 /**
243 * Result of forwarding number change.
244 * Keys are reasons (eg. unconditional forwarding).
245 */
246 private Map<Integer, AsyncResult> mForwardingChangeResults = null;
247
248 /**
249 * Expected CF read result types.
250 * This set keeps track of the CF types for which we've issued change
251 * commands so we can tell when we've received all of the responses.
252 */
253 private Collection<Integer> mExpectedChangeResultReasons = null;
254
255 /**
256 * Result of vm number change
257 */
258 private AsyncResult mVoicemailChangeResult = null;
259
260 /**
261 * Previous VM provider setting so we can return to it in case of failure.
262 */
263 private String mPreviousVMProviderKey = null;
264
265 /**
266 * Id of the dialog being currently shown.
267 */
268 private int mCurrentDialogId = 0;
269
270 /**
271 * Flag indicating that we are invoking settings for the voicemail provider programmatically
272 * due to vm provider change.
273 */
274 private boolean mVMProviderSettingsForced = false;
275
276 /**
277 * Flag indicating that we are making changes to vm or fwd numbers
278 * due to vm provider change.
279 */
280 private boolean mChangingVMorFwdDueToProviderChange = false;
281
282 /**
283 * True if we are in the process of vm & fwd number change and vm has already been changed.
284 * This is used to decide what to do in case of rollback.
285 */
286 private boolean mVMChangeCompletedSuccessfully = false;
287
288 /**
289 * True if we had full or partial failure setting forwarding numbers and so need to roll them
290 * back.
291 */
292 private boolean mFwdChangesRequireRollback = false;
293
294 /**
295 * Id of error msg to display to user once we are done reverting the VM provider to the previous
296 * one.
297 */
298 private int mVMOrFwdSetError = 0;
299
300 /**
301 * Data about discovered voice mail settings providers.
302 * Is populated by querying which activities can handle ACTION_CONFIGURE_VOICEMAIL.
303 * They key in this map is package name + activity name.
304 * We always add an entry for the default provider with a key of empty
305 * string and intent value of null.
306 * @see #initVoiceMailProviders()
307 */
308 private final Map<String, VoiceMailProvider> mVMProvidersData =
309 new HashMap<String, VoiceMailProvider>();
310
311 /** string to hold old voicemail number as it is being updated. */
312 private String mOldVmNumber;
313
314 // New call forwarding settings and vm number we will be setting
315 // Need to save these since before we get to saving we need to asynchronously
316 // query the existing forwarding settings.
317 private CallForwardInfo[] mNewFwdSettings;
318 private String mNewVMNumber;
319
320 private boolean mForeground;
321
322 @Override
323 public void onPause() {
324 super.onPause();
325 mForeground = false;
326 }
327
328 /**
329 * We have to pull current settings from the network for all kinds of
330 * voicemail providers so we can tell whether we have to update them,
331 * so use this bit to keep track of whether we're reading settings for the
332 * default provider and should therefore save them out when done.
333 */
334 private boolean mReadingSettingsForDefaultProvider = false;
335
Tyler Gunnbaee2952014-09-10 16:01:02 -0700336 /**
337 * Used to indicate that the voicemail preference should be shown.
338 */
339 private boolean mShowVoicemailPreference = false;
340
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700341 /*
342 * Click Listeners, handle click based on objects attached to UI.
343 */
344
345 // Click listener for all toggle events
346 @Override
347 public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
348 if (preference == mSubMenuVoicemailSettings) {
349 return true;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700350 } else if (preference == mButtonDTMF) {
351 return true;
352 } else if (preference == mButtonTTY) {
353 return true;
354 } else if (preference == mButtonAutoRetry) {
355 android.provider.Settings.Global.putInt(mPhone.getContext().getContentResolver(),
356 android.provider.Settings.Global.CALL_AUTO_RETRY,
357 mButtonAutoRetry.isChecked() ? 1 : 0);
358 return true;
359 } else if (preference == mButtonHAC) {
360 int hac = mButtonHAC.isChecked() ? 1 : 0;
361 // Update HAC value in Settings database
362 Settings.System.putInt(mPhone.getContext().getContentResolver(),
363 Settings.System.HEARING_AID, hac);
364
365 // Update HAC Value in AudioManager
366 mAudioManager.setParameter(HAC_KEY, hac != 0 ? HAC_VAL_ON : HAC_VAL_OFF);
367 return true;
368 } else if (preference == mVoicemailSettings) {
Yorke Leea0f63bf2014-10-09 18:27:20 -0700369 final Dialog dialog = mVoicemailSettings.getDialog();
370 if (dialog != null) {
371 dialog.getActionBar().setDisplayHomeAsUpEnabled(false);
372 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700373 if (DBG) log("onPreferenceTreeClick: Voicemail Settings Preference is clicked.");
374 if (preference.getIntent() != null) {
375 if (DBG) {
376 log("onPreferenceTreeClick: Invoking cfg intent "
377 + preference.getIntent().getPackage());
378 }
379
380 // onActivityResult() will be responsible for resetting some of variables.
381 this.startActivityForResult(preference.getIntent(), VOICEMAIL_PROVIDER_CFG_ID);
382 return true;
383 } else {
384 if (DBG) {
385 log("onPreferenceTreeClick:"
386 + " No Intent is available. Use default behavior defined in xml.");
387 }
388
389 // There's no onActivityResult(), so we need to take care of some of variables
390 // which should be reset here.
391 mPreviousVMProviderKey = DEFAULT_VM_PROVIDER_KEY;
392 mVMProviderSettingsForced = false;
393
394 // This should let the preference use default behavior in the xml.
395 return false;
396 }
Andrew Lee97708a42014-09-25 12:39:07 -0700397 } else if (preference == mVoicemailSettingsScreen) {
Yorke Leea0f63bf2014-10-09 18:27:20 -0700398 final Dialog dialog = mVoicemailSettingsScreen.getDialog();
399 if (dialog != null) {
400 dialog.getActionBar().setDisplayHomeAsUpEnabled(false);
401 }
Andrew Lee97708a42014-09-25 12:39:07 -0700402 return false;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700403 }
404 return false;
405 }
406
407 /**
408 * Implemented to support onPreferenceChangeListener to look for preference
409 * changes.
410 *
411 * @param preference is the preference to be changed
412 * @param objValue should be the value of the selection, NOT its localized
413 * display value.
414 */
415 @Override
416 public boolean onPreferenceChange(Preference preference, Object objValue) {
417 if (DBG) {
Andrew Leedf14ead2014-10-17 14:22:52 -0700418 log("onPreferenceChange(). preference: \"" + preference + "\""
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700419 + ", value: \"" + objValue + "\"");
420 }
Andrew Lee2170a972014-08-13 18:13:01 -0700421
422 if (preference == mButtonDTMF) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700423 int index = mButtonDTMF.findIndexOfValue((String) objValue);
424 Settings.System.putInt(mPhone.getContext().getContentResolver(),
425 Settings.System.DTMF_TONE_TYPE_WHEN_DIALING, index);
426 } else if (preference == mButtonTTY) {
427 handleTTYChange(preference, objValue);
428 } else if (preference == mVoicemailProviders) {
429 final String newProviderKey = (String) objValue;
430 if (DBG) {
431 log("Voicemail Provider changes from \"" + mPreviousVMProviderKey
432 + "\" to \"" + newProviderKey + "\".");
433 }
434 // If previous provider key and the new one is same, we don't need to handle it.
435 if (mPreviousVMProviderKey.equals(newProviderKey)) {
436 if (DBG) log("No change is made toward VM provider setting.");
437 return true;
438 }
439 updateVMPreferenceWidgets(newProviderKey);
440
Andrew Leeb490d732014-10-27 15:00:41 -0700441 final VoicemailProviderSettings newProviderSettings =
Andrew Lee88b51e22014-10-29 15:48:51 -0700442 mVmProviderSettingsUtil.load(newProviderKey);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700443
Andrew Lee88b51e22014-10-29 15:48:51 -0700444 // If the user switches to a voice mail provider and we have numbers stored for it we
445 // will automatically change the phone's voice mail and forwarding number to the stored
446 // ones. Otherwise we will bring up provider's configuration UI.
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700447 if (newProviderSettings == null) {
448 // Force the user into a configuration of the chosen provider
449 Log.w(LOG_TAG, "Saved preferences not found - invoking config");
450 mVMProviderSettingsForced = true;
451 simulatePreferenceClick(mVoicemailSettings);
452 } else {
453 if (DBG) log("Saved preferences found - switching to them");
454 // Set this flag so if we get a failure we revert to previous provider
455 mChangingVMorFwdDueToProviderChange = true;
456 saveVoiceMailAndForwardingNumber(newProviderKey, newProviderSettings);
457 }
Andrew Leedf14ead2014-10-17 14:22:52 -0700458 } else if (preference == mEnableVideoCalling) {
Andrew Lee312e8172014-10-23 17:01:36 -0700459 if (ImsManager.isEnhanced4gLteModeSettingEnabledByUser(mPhone.getContext())) {
460 PhoneGlobals.getInstance().phoneMgr.enableVideoCalling((boolean) objValue);
461 } else {
462 AlertDialog.Builder builder = new AlertDialog.Builder(this);
463 DialogInterface.OnClickListener networkSettingsClickListener =
464 new Dialog.OnClickListener() {
465 @Override
466 public void onClick(DialogInterface dialog, int which) {
467 startActivity(new Intent(mPhone.getContext(),
468 com.android.phone.MobileNetworkSettings.class));
469 }
470 };
471 builder.setMessage(getResources().getString(
472 R.string.enable_video_calling_dialog_msg))
473 .setNeutralButton(getResources().getString(
474 R.string.enable_video_calling_dialog_settings),
475 networkSettingsClickListener)
476 .setPositiveButton(android.R.string.ok, null)
477 .show();
478 return false;
479 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700480 }
481 // always let the preference setting proceed.
482 return true;
483 }
484
485 @Override
486 public void onDialogClosed(EditPhoneNumberPreference preference, int buttonClicked) {
487 if (DBG) log("onPreferenceClick: request preference click on dialog close: " +
488 buttonClicked);
489 if (buttonClicked == DialogInterface.BUTTON_NEGATIVE) {
490 return;
491 }
492
493 if (preference == mSubMenuVoicemailSettings) {
Andrew Leee438b312014-10-29 16:59:15 -0700494 VoicemailProviderSettings newSettings = new VoicemailProviderSettings(
495 mSubMenuVoicemailSettings.getPhoneNumber(),
496 VoicemailProviderSettings.NO_FORWARDING);
497 saveVoiceMailAndForwardingNumber(getCurrentVoicemailProviderKey(), newSettings);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700498 }
499 }
500
501 /**
502 * Implemented for EditPhoneNumberPreference.GetDefaultNumberListener.
503 * This method set the default values for the various
504 * EditPhoneNumberPreference dialogs.
505 */
506 @Override
507 public String onGetDefaultNumber(EditPhoneNumberPreference preference) {
508 if (preference == mSubMenuVoicemailSettings) {
509 // update the voicemail number field, which takes care of the
510 // mSubMenuVoicemailSettings itself, so we should return null.
511 if (DBG) log("updating default for voicemail dialog");
512 updateVoiceNumberField();
513 return null;
514 }
515
516 String vmDisplay = mPhone.getVoiceMailNumber();
517 if (TextUtils.isEmpty(vmDisplay)) {
518 // if there is no voicemail number, we just return null to
519 // indicate no contribution.
520 return null;
521 }
522
523 // Return the voicemail number prepended with "VM: "
524 if (DBG) log("updating default for call forwarding dialogs");
525 return getString(R.string.voicemail_abbreviated) + " " + vmDisplay;
526 }
527
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700528 private void switchToPreviousVoicemailProvider() {
529 if (DBG) log("switchToPreviousVoicemailProvider " + mPreviousVMProviderKey);
530 if (mPreviousVMProviderKey != null) {
531 if (mVMChangeCompletedSuccessfully || mFwdChangesRequireRollback) {
532 // we have to revert with carrier
533 if (DBG) {
534 log("Needs to rollback."
535 + " mVMChangeCompletedSuccessfully=" + mVMChangeCompletedSuccessfully
536 + ", mFwdChangesRequireRollback=" + mFwdChangesRequireRollback);
537 }
538
539 showDialogIfForeground(VOICEMAIL_REVERTING_DIALOG);
Andrew Leeb490d732014-10-27 15:00:41 -0700540 final VoicemailProviderSettings prevSettings =
Andrew Lee88b51e22014-10-29 15:48:51 -0700541 mVmProviderSettingsUtil.load(mPreviousVMProviderKey);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700542 if (prevSettings == null) {
543 // prevSettings never becomes null since it should be already loaded!
Andrew Leeb490d732014-10-27 15:00:41 -0700544 Log.e(LOG_TAG, "VoicemailProviderSettings for the key \""
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700545 + mPreviousVMProviderKey + "\" becomes null, which is unexpected.");
546 if (DBG) {
547 Log.e(LOG_TAG,
548 "mVMChangeCompletedSuccessfully: " + mVMChangeCompletedSuccessfully
549 + ", mFwdChangesRequireRollback: " + mFwdChangesRequireRollback);
550 }
551 }
552 if (mVMChangeCompletedSuccessfully) {
Andrew Leeb490d732014-10-27 15:00:41 -0700553 mNewVMNumber = prevSettings.getVoicemailNumber();
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700554 Log.i(LOG_TAG, "VM change is already completed successfully."
555 + "Have to revert VM back to " + mNewVMNumber + " again.");
556 mPhone.setVoiceMailNumber(
557 mPhone.getVoiceMailAlphaTag().toString(),
558 mNewVMNumber,
559 Message.obtain(mRevertOptionComplete, EVENT_VOICEMAIL_CHANGED));
560 }
561 if (mFwdChangesRequireRollback) {
562 Log.i(LOG_TAG, "Requested to rollback Fwd changes.");
Andrew Leeb490d732014-10-27 15:00:41 -0700563 final CallForwardInfo[] prevFwdSettings = prevSettings.getForwardingSettings();
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700564 if (prevFwdSettings != null) {
565 Map<Integer, AsyncResult> results =
566 mForwardingChangeResults;
567 resetForwardingChangeState();
568 for (int i = 0; i < prevFwdSettings.length; i++) {
569 CallForwardInfo fi = prevFwdSettings[i];
570 if (DBG) log("Reverting fwd #: " + i + ": " + fi.toString());
571 // Only revert the settings for which the update
572 // succeeded
573 AsyncResult result = results.get(fi.reason);
574 if (result != null && result.exception == null) {
575 mExpectedChangeResultReasons.add(fi.reason);
576 mPhone.setCallForwardingOption(
577 (fi.status == 1 ?
578 CommandsInterface.CF_ACTION_REGISTRATION :
579 CommandsInterface.CF_ACTION_DISABLE),
580 fi.reason,
581 fi.number,
582 fi.timeSeconds,
583 mRevertOptionComplete.obtainMessage(
584 EVENT_FORWARDING_CHANGED, i, 0));
585 }
586 }
587 }
588 }
589 } else {
590 if (DBG) log("No need to revert");
591 onRevertDone();
592 }
593 }
594 }
595
596 private void onRevertDone() {
597 if (DBG) log("Flipping provider key back to " + mPreviousVMProviderKey);
598 mVoicemailProviders.setValue(mPreviousVMProviderKey);
599 updateVMPreferenceWidgets(mPreviousVMProviderKey);
600 updateVoiceNumberField();
601 if (mVMOrFwdSetError != 0) {
Andrew Leeab082272014-11-04 15:50:42 -0800602 showDialogIfForeground(mVMOrFwdSetError);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700603 mVMOrFwdSetError = 0;
604 }
605 }
606
607 @Override
608 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
609 if (DBG) {
610 log("onActivityResult: requestCode: " + requestCode
611 + ", resultCode: " + resultCode
612 + ", data: " + data);
613 }
614 // there are cases where the contact picker may end up sending us more than one
615 // request. We want to ignore the request if we're not in the correct state.
616 if (requestCode == VOICEMAIL_PROVIDER_CFG_ID) {
617 boolean failure = false;
618
619 // No matter how the processing of result goes lets clear the flag
620 if (DBG) log("mVMProviderSettingsForced: " + mVMProviderSettingsForced);
621 final boolean isVMProviderSettingsForced = mVMProviderSettingsForced;
622 mVMProviderSettingsForced = false;
623
624 String vmNum = null;
625 if (resultCode != RESULT_OK) {
626 if (DBG) log("onActivityResult: vm provider cfg result not OK.");
627 failure = true;
628 } else {
629 if (data == null) {
630 if (DBG) log("onActivityResult: vm provider cfg result has no data");
631 failure = true;
632 } else {
633 if (data.getBooleanExtra(SIGNOUT_EXTRA, false)) {
634 if (DBG) log("Provider requested signout");
635 if (isVMProviderSettingsForced) {
636 if (DBG) log("Going back to previous provider on signout");
637 switchToPreviousVoicemailProvider();
638 } else {
639 final String victim = getCurrentVoicemailProviderKey();
640 if (DBG) log("Relaunching activity and ignoring " + victim);
641 Intent i = new Intent(ACTION_ADD_VOICEMAIL);
642 i.putExtra(IGNORE_PROVIDER_EXTRA, victim);
643 i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
644 this.startActivity(i);
645 }
646 return;
647 }
648 vmNum = data.getStringExtra(VM_NUMBER_EXTRA);
649 if (vmNum == null || vmNum.length() == 0) {
650 if (DBG) log("onActivityResult: vm provider cfg result has no vmnum");
651 failure = true;
652 }
653 }
654 }
655 if (failure) {
656 if (DBG) log("Failure in return from voicemail provider");
657 if (isVMProviderSettingsForced) {
658 switchToPreviousVoicemailProvider();
659 } else {
660 if (DBG) log("Not switching back the provider since this is not forced config");
661 }
662 return;
663 }
664 mChangingVMorFwdDueToProviderChange = isVMProviderSettingsForced;
665 final String fwdNum = data.getStringExtra(FWD_NUMBER_EXTRA);
666
Santos Cordonda120f42014-08-06 04:44:34 -0700667 // TODO: It would be nice to load the current network setting for this and
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700668 // send it to the provider when it's config is invoked so it can use this as default
669 final int fwdNumTime = data.getIntExtra(FWD_NUMBER_TIME_EXTRA, 20);
670
671 if (DBG) log("onActivityResult: vm provider cfg result " +
672 (fwdNum != null ? "has" : " does not have") + " forwarding number");
673 saveVoiceMailAndForwardingNumber(getCurrentVoicemailProviderKey(),
Andrew Leeb490d732014-10-27 15:00:41 -0700674 new VoicemailProviderSettings(vmNum, fwdNum, fwdNumTime));
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700675 return;
676 }
677
678 if (requestCode == VOICEMAIL_PREF_ID) {
679 if (resultCode != RESULT_OK) {
680 if (DBG) log("onActivityResult: contact picker result not OK.");
681 return;
682 }
683
684 Cursor cursor = null;
685 try {
686 cursor = getContentResolver().query(data.getData(),
687 NUM_PROJECTION, null, null, null);
688 if ((cursor == null) || (!cursor.moveToFirst())) {
689 if (DBG) log("onActivityResult: bad contact data, no results found.");
690 return;
691 }
692 mSubMenuVoicemailSettings.onPickActivityResult(cursor.getString(0));
693 return;
694 } finally {
695 if (cursor != null) {
696 cursor.close();
697 }
698 }
699 }
700
701 super.onActivityResult(requestCode, resultCode, data);
702 }
703
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700704 /**
705 * Wrapper around showDialog() that will silently do nothing if we're
706 * not in the foreground.
707 *
708 * This is useful here because most of the dialogs we display from
709 * this class are triggered by asynchronous events (like
710 * success/failure messages from the telephony layer) and it's
711 * possible for those events to come in even after the user has gone
712 * to a different screen.
713 */
714 // TODO: this is too brittle: it's still easy to accidentally add new
715 // code here that calls showDialog() directly (which will result in a
716 // WindowManager$BadTokenException if called after the activity has
717 // been stopped.)
718 //
719 // It would be cleaner to do the "if (mForeground)" check in one
720 // central place, maybe by using a single Handler for all asynchronous
721 // events (and have *that* discard events if we're not in the
722 // foreground.)
723 //
724 // Unfortunately it's not that simple, since we sometimes need to do
725 // actual work to handle these events whether or not we're in the
726 // foreground (see the Handler code in mSetOptionComplete for
727 // example.)
Andrew Leeab082272014-11-04 15:50:42 -0800728 //
729 // TODO: It's a bit worrisome that we don't do anything in error cases when we're not in the
730 // foreground. Consider displaying a toast instead.
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700731 private void showDialogIfForeground(int id) {
732 if (mForeground) {
733 showDialog(id);
734 }
735 }
736
737 private void dismissDialogSafely(int id) {
738 try {
739 dismissDialog(id);
740 } catch (IllegalArgumentException e) {
741 // This is expected in the case where we were in the background
742 // at the time we would normally have shown the dialog, so we didn't
743 // show it.
744 }
745 }
746
Andrew Leeb490d732014-10-27 15:00:41 -0700747 private void saveVoiceMailAndForwardingNumber(
748 String key, VoicemailProviderSettings newSettings) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700749 if (DBG) log("saveVoiceMailAndForwardingNumber: " + newSettings.toString());
Andrew Leeb490d732014-10-27 15:00:41 -0700750 mNewVMNumber = newSettings.getVoicemailNumber();
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700751 // empty vm number == clearing the vm number ?
752 if (mNewVMNumber == null) {
753 mNewVMNumber = "";
754 }
755
Andrew Leeb490d732014-10-27 15:00:41 -0700756 mNewFwdSettings = newSettings.getForwardingSettings();
757 if (DBG) log("newFwdNumber "
758 + String.valueOf((mNewFwdSettings != null ? mNewFwdSettings.length : 0))
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700759 + " settings");
760
761 // No fwd settings on CDMA
762 if (mPhone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA) {
763 if (DBG) log("ignoring forwarding setting since this is CDMA phone");
Andrew Leeb490d732014-10-27 15:00:41 -0700764 mNewFwdSettings = VoicemailProviderSettings.NO_FORWARDING;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700765 }
766
Andrew Leee3c15212014-10-28 13:12:55 -0700767 // Throw a warning if the voicemail is the same and we did not change forwarding.
Andrew Leeb490d732014-10-27 15:00:41 -0700768 if (mNewVMNumber.equals(mOldVmNumber)
769 && mNewFwdSettings == VoicemailProviderSettings.NO_FORWARDING) {
Andrew Leeab082272014-11-04 15:50:42 -0800770 showDialogIfForeground(VM_NOCHANGE_ERROR);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700771 return;
772 }
773
Andrew Lee88b51e22014-10-29 15:48:51 -0700774 mVmProviderSettingsUtil.save(key, newSettings);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700775 mVMChangeCompletedSuccessfully = false;
776 mFwdChangesRequireRollback = false;
777 mVMOrFwdSetError = 0;
778 if (!key.equals(mPreviousVMProviderKey)) {
779 mReadingSettingsForDefaultProvider =
780 mPreviousVMProviderKey.equals(DEFAULT_VM_PROVIDER_KEY);
781 if (DBG) log("Reading current forwarding settings");
Andrew Leeb490d732014-10-27 15:00:41 -0700782 int numSettingsReasons = VoicemailProviderSettings.FORWARDING_SETTINGS_REASONS.length;
783 mForwardingReadResults = new CallForwardInfo[numSettingsReasons];
784 for (int i = 0; i < mForwardingReadResults.length; i++) {
785 mPhone.getCallForwardingOption(
786 VoicemailProviderSettings.FORWARDING_SETTINGS_REASONS[i],
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700787 mGetOptionComplete.obtainMessage(EVENT_FORWARDING_GET_COMPLETED, i, 0));
788 }
789 showDialogIfForeground(VOICEMAIL_FWD_READING_DIALOG);
790 } else {
791 saveVoiceMailAndForwardingNumberStage2();
792 }
793 }
794
795 private final Handler mGetOptionComplete = new Handler() {
796 @Override
797 public void handleMessage(Message msg) {
798 AsyncResult result = (AsyncResult) msg.obj;
799 switch (msg.what) {
800 case EVENT_FORWARDING_GET_COMPLETED:
801 handleForwardingSettingsReadResult(result, msg.arg1);
802 break;
803 }
804 }
805 };
806
807 private void handleForwardingSettingsReadResult(AsyncResult ar, int idx) {
808 if (DBG) Log.d(LOG_TAG, "handleForwardingSettingsReadResult: " + idx);
809 Throwable error = null;
810 if (ar.exception != null) {
811 if (DBG) Log.d(LOG_TAG, "FwdRead: ar.exception=" +
812 ar.exception.getMessage());
813 error = ar.exception;
814 }
815 if (ar.userObj instanceof Throwable) {
816 if (DBG) Log.d(LOG_TAG, "FwdRead: userObj=" +
817 ((Throwable)ar.userObj).getMessage());
818 error = (Throwable)ar.userObj;
819 }
820
821 // We may have already gotten an error and decided to ignore the other results.
822 if (mForwardingReadResults == null) {
823 if (DBG) Log.d(LOG_TAG, "ignoring fwd reading result: " + idx);
824 return;
825 }
826
827 // In case of error ignore other results, show an error dialog
828 if (error != null) {
829 if (DBG) Log.d(LOG_TAG, "Error discovered for fwd read : " + idx);
830 mForwardingReadResults = null;
831 dismissDialogSafely(VOICEMAIL_FWD_READING_DIALOG);
Andrew Leeab082272014-11-04 15:50:42 -0800832 showDialogIfForeground(FW_GET_RESPONSE_ERROR);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700833 return;
834 }
835
836 // Get the forwarding info
837 final CallForwardInfo cfInfoArray[] = (CallForwardInfo[]) ar.result;
838 CallForwardInfo fi = null;
839 for (int i = 0 ; i < cfInfoArray.length; i++) {
840 if ((cfInfoArray[i].serviceClass & CommandsInterface.SERVICE_CLASS_VOICE) != 0) {
841 fi = cfInfoArray[i];
842 break;
843 }
844 }
845 if (fi == null) {
846
847 // In case we go nothing it means we need this reason disabled
848 // so create a CallForwardInfo for capturing this
849 if (DBG) Log.d(LOG_TAG, "Creating default info for " + idx);
850 fi = new CallForwardInfo();
851 fi.status = 0;
Andrew Leeb490d732014-10-27 15:00:41 -0700852 fi.reason = VoicemailProviderSettings.FORWARDING_SETTINGS_REASONS[idx];
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700853 fi.serviceClass = CommandsInterface.SERVICE_CLASS_VOICE;
854 } else {
855 // if there is not a forwarding number, ensure the entry is set to "not active."
856 if (fi.number == null || fi.number.length() == 0) {
857 fi.status = 0;
858 }
859
860 if (DBG) Log.d(LOG_TAG, "Got " + fi.toString() + " for " + idx);
861 }
862 mForwardingReadResults[idx] = fi;
863
864 // Check if we got all the results already
865 boolean done = true;
866 for (int i = 0; i < mForwardingReadResults.length; i++) {
867 if (mForwardingReadResults[i] == null) {
868 done = false;
869 break;
870 }
871 }
872 if (done) {
873 if (DBG) Log.d(LOG_TAG, "Done receiving fwd info");
874 dismissDialogSafely(VOICEMAIL_FWD_READING_DIALOG);
875 if (mReadingSettingsForDefaultProvider) {
Andrew Lee88b51e22014-10-29 15:48:51 -0700876 mVmProviderSettingsUtil.save(DEFAULT_VM_PROVIDER_KEY,
877 new VoicemailProviderSettings(this.mOldVmNumber, mForwardingReadResults));
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700878 mReadingSettingsForDefaultProvider = false;
879 }
880 saveVoiceMailAndForwardingNumberStage2();
881 } else {
882 if (DBG) Log.d(LOG_TAG, "Not done receiving fwd info");
883 }
884 }
885
886 private CallForwardInfo infoForReason(CallForwardInfo[] infos, int reason) {
887 CallForwardInfo result = null;
888 if (null != infos) {
889 for (CallForwardInfo info : infos) {
890 if (info.reason == reason) {
891 result = info;
892 break;
893 }
894 }
895 }
896 return result;
897 }
898
Andrew Leee438b312014-10-29 16:59:15 -0700899 private boolean isUpdateRequired(CallForwardInfo oldInfo, CallForwardInfo newInfo) {
900 if (oldInfo == null) {
901 return true;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700902 }
Andrew Leee438b312014-10-29 16:59:15 -0700903
904 // If we're disabling a type of forwarding, don't make any change if it's already disabled.
905 if (newInfo.status == CALL_FORWARD_INFO_INACTIVE_STATUS
906 && oldInfo.status == CALL_FORWARD_INFO_INACTIVE_STATUS) {
907 return false;
908 }
909
910 return true;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700911 }
912
913 private void resetForwardingChangeState() {
914 mForwardingChangeResults = new HashMap<Integer, AsyncResult>();
915 mExpectedChangeResultReasons = new HashSet<Integer>();
916 }
917
918 // Called after we are done saving the previous forwarding settings if
919 // we needed.
920 private void saveVoiceMailAndForwardingNumberStage2() {
921 mForwardingChangeResults = null;
922 mVoicemailChangeResult = null;
Andrew Leeb490d732014-10-27 15:00:41 -0700923 if (mNewFwdSettings != VoicemailProviderSettings.NO_FORWARDING) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700924 resetForwardingChangeState();
925 for (int i = 0; i < mNewFwdSettings.length; i++) {
926 CallForwardInfo fi = mNewFwdSettings[i];
927
928 final boolean doUpdate = isUpdateRequired(infoForReason(
929 mForwardingReadResults, fi.reason), fi);
930
931 if (doUpdate) {
932 if (DBG) log("Setting fwd #: " + i + ": " + fi.toString());
933 mExpectedChangeResultReasons.add(i);
934
935 mPhone.setCallForwardingOption(
936 fi.status == 1 ?
937 CommandsInterface.CF_ACTION_REGISTRATION :
938 CommandsInterface.CF_ACTION_DISABLE,
939 fi.reason,
940 fi.number,
941 fi.timeSeconds,
942 mSetOptionComplete.obtainMessage(
943 EVENT_FORWARDING_CHANGED, fi.reason, 0));
944 }
945 }
946 showDialogIfForeground(VOICEMAIL_FWD_SAVING_DIALOG);
947 } else {
948 if (DBG) log("Not touching fwd #");
949 setVMNumberWithCarrier();
950 }
951 }
952
953 private void setVMNumberWithCarrier() {
954 if (DBG) log("save voicemail #: " + mNewVMNumber);
955 mPhone.setVoiceMailNumber(
956 mPhone.getVoiceMailAlphaTag().toString(),
957 mNewVMNumber,
958 Message.obtain(mSetOptionComplete, EVENT_VOICEMAIL_CHANGED));
959 }
960
961 /**
962 * Callback to handle option update completions
963 */
964 private final Handler mSetOptionComplete = new Handler() {
965 @Override
966 public void handleMessage(Message msg) {
967 AsyncResult result = (AsyncResult) msg.obj;
968 boolean done = false;
969 switch (msg.what) {
970 case EVENT_VOICEMAIL_CHANGED:
971 mVoicemailChangeResult = result;
Andrew Leee438b312014-10-29 16:59:15 -0700972 mVMChangeCompletedSuccessfully = isVmChangeSuccess();
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700973 done = true;
974 break;
975 case EVENT_FORWARDING_CHANGED:
976 mForwardingChangeResults.put(msg.arg1, result);
977 if (result.exception != null) {
978 Log.w(LOG_TAG, "Error in setting fwd# " + msg.arg1 + ": " +
979 result.exception.getMessage());
980 } else {
981 if (DBG) log("Success in setting fwd# " + msg.arg1);
982 }
Andrew Leee438b312014-10-29 16:59:15 -0700983 if (isForwardingCompleted()) {
984 if (isFwdChangeSuccess()) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700985 if (DBG) log("Overall fwd changes completed ok, starting vm change");
986 setVMNumberWithCarrier();
987 } else {
988 Log.w(LOG_TAG, "Overall fwd changes completed in failure. " +
989 "Check if we need to try rollback for some settings.");
990 mFwdChangesRequireRollback = false;
991 Iterator<Map.Entry<Integer,AsyncResult>> it =
992 mForwardingChangeResults.entrySet().iterator();
993 while (it.hasNext()) {
994 Map.Entry<Integer,AsyncResult> entry = it.next();
995 if (entry.getValue().exception == null) {
996 // If at least one succeeded we have to revert
997 Log.i(LOG_TAG, "Rollback will be required");
998 mFwdChangesRequireRollback = true;
999 break;
1000 }
1001 }
1002 if (!mFwdChangesRequireRollback) {
1003 Log.i(LOG_TAG, "No rollback needed.");
1004 }
1005 done = true;
1006 }
1007 }
1008 break;
1009 default:
1010 // TODO: should never reach this, may want to throw exception
1011 }
1012 if (done) {
1013 if (DBG) log("All VM provider related changes done");
1014 if (mForwardingChangeResults != null) {
1015 dismissDialogSafely(VOICEMAIL_FWD_SAVING_DIALOG);
1016 }
Andrew Leee438b312014-10-29 16:59:15 -07001017 handleSetVmOrFwdMessage();
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001018 }
1019 }
1020 };
1021
1022 /**
1023 * Callback to handle option revert completions
1024 */
1025 private final Handler mRevertOptionComplete = new Handler() {
1026 @Override
1027 public void handleMessage(Message msg) {
1028 AsyncResult result = (AsyncResult) msg.obj;
1029 switch (msg.what) {
1030 case EVENT_VOICEMAIL_CHANGED:
1031 mVoicemailChangeResult = result;
1032 if (DBG) log("VM revert complete msg");
1033 break;
1034 case EVENT_FORWARDING_CHANGED:
1035 mForwardingChangeResults.put(msg.arg1, result);
1036 if (result.exception != null) {
1037 if (DBG) log("Error in reverting fwd# " + msg.arg1 + ": " +
1038 result.exception.getMessage());
1039 } else {
1040 if (DBG) log("Success in reverting fwd# " + msg.arg1);
1041 }
1042 if (DBG) log("FWD revert complete msg ");
1043 break;
1044 default:
1045 // TODO: should never reach this, may want to throw exception
1046 }
1047 final boolean done =
1048 (!mVMChangeCompletedSuccessfully || mVoicemailChangeResult != null) &&
Andrew Leee438b312014-10-29 16:59:15 -07001049 (!mFwdChangesRequireRollback || isForwardingCompleted());
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001050 if (done) {
1051 if (DBG) log("All VM reverts done");
1052 dismissDialogSafely(VOICEMAIL_REVERTING_DIALOG);
1053 onRevertDone();
1054 }
1055 }
1056 };
1057
1058 /**
Andrew Leee438b312014-10-29 16:59:15 -07001059 * Return true if there is a change result for every reason for which we expect a result.
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001060 */
Andrew Leee438b312014-10-29 16:59:15 -07001061 private boolean isForwardingCompleted() {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001062 if (mForwardingChangeResults == null) {
Andrew Leee438b312014-10-29 16:59:15 -07001063 return true;
1064 }
1065
1066 for (Integer reason : mExpectedChangeResultReasons) {
1067 if (mForwardingChangeResults.get(reason) == null) {
1068 return false;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001069 }
1070 }
Andrew Leee438b312014-10-29 16:59:15 -07001071
1072 return true;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001073 }
Andrew Leee438b312014-10-29 16:59:15 -07001074
1075 private boolean isFwdChangeSuccess() {
1076 if (mForwardingChangeResults == null) {
1077 return true;
1078 }
1079
1080 for (AsyncResult result : mForwardingChangeResults.values()) {
1081 Throwable exception = result.exception;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001082 if (exception != null) {
Andrew Leee438b312014-10-29 16:59:15 -07001083 String msg = exception.getMessage();
1084 msg = (msg != null) ? msg : "";
1085 Log.w(LOG_TAG, "Failed to change forwarding setting. Reason: " + msg);
1086 return false;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001087 }
1088 }
Andrew Leee438b312014-10-29 16:59:15 -07001089 return true;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001090 }
1091
Andrew Leee438b312014-10-29 16:59:15 -07001092 private boolean isVmChangeSuccess() {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001093 if (mVoicemailChangeResult.exception != null) {
Andrew Leee438b312014-10-29 16:59:15 -07001094 String msg = mVoicemailChangeResult.exception.getMessage();
1095 msg = (msg != null) ? msg : "";
1096 Log.w(LOG_TAG, "Failed to change voicemail. Reason: " + msg);
1097 return false;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001098 }
Andrew Leee438b312014-10-29 16:59:15 -07001099
1100 if (DBG) log("VM change completed successfully.");
1101 return true;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001102 }
1103
Andrew Leee438b312014-10-29 16:59:15 -07001104 private void handleSetVmOrFwdMessage() {
1105 if (DBG) log("handleSetVMMessage: set VM request complete");
1106
1107 if (!isFwdChangeSuccess()) {
Andrew Leeab082272014-11-04 15:50:42 -08001108 handleVmOrFwdSetError(FW_SET_RESPONSE_ERROR);
Andrew Leee438b312014-10-29 16:59:15 -07001109 } else if (!isVmChangeSuccess()) {
Andrew Leeab082272014-11-04 15:50:42 -08001110 handleVmOrFwdSetError(VM_RESPONSE_ERROR);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001111 } else {
Andrew Leee438b312014-10-29 16:59:15 -07001112 if (DBG) log("change VM success!");
Andrew Leeab082272014-11-04 15:50:42 -08001113 handleVmAndFwdSetSuccess(VOICEMAIL_DIALOG_CONFIRM);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001114 }
1115 }
1116
1117 /**
1118 * Called when Voicemail Provider or its forwarding settings failed. Rolls back partly made
1119 * changes to those settings and show "failure" dialog.
1120 *
Andrew Leeab082272014-11-04 15:50:42 -08001121 * @param dialogId ID of the dialog to show for the specific error case. Either
1122 * {@link #FW_SET_RESPONSE_ERROR} or {@link #VM_RESPONSE_ERROR}
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001123 */
Andrew Leeab082272014-11-04 15:50:42 -08001124 private void handleVmOrFwdSetError(int dialogId) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001125 if (mChangingVMorFwdDueToProviderChange) {
Andrew Leeab082272014-11-04 15:50:42 -08001126 mVMOrFwdSetError = dialogId;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001127 mChangingVMorFwdDueToProviderChange = false;
1128 switchToPreviousVoicemailProvider();
1129 return;
1130 }
1131 mChangingVMorFwdDueToProviderChange = false;
Andrew Leeab082272014-11-04 15:50:42 -08001132 showDialogIfForeground(dialogId);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001133 updateVoiceNumberField();
1134 }
1135
1136 /**
1137 * Called when Voicemail Provider and its forwarding settings were successfully finished.
1138 * This updates a bunch of variables and show "success" dialog.
1139 */
Andrew Leeab082272014-11-04 15:50:42 -08001140 private void handleVmAndFwdSetSuccess(int dialogId) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001141 if (DBG) {
Andrew Leee438b312014-10-29 16:59:15 -07001142 log("handleVmAndFwdSetSuccess(). current voicemail provider key: "
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001143 + getCurrentVoicemailProviderKey());
1144 }
1145 mPreviousVMProviderKey = getCurrentVoicemailProviderKey();
1146 mChangingVMorFwdDueToProviderChange = false;
Andrew Leeab082272014-11-04 15:50:42 -08001147 showDialogIfForeground(dialogId);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001148 updateVoiceNumberField();
1149 }
1150
1151 /**
1152 * Update the voicemail number from what we've recorded on the sim.
1153 */
1154 private void updateVoiceNumberField() {
1155 if (DBG) {
1156 log("updateVoiceNumberField(). mSubMenuVoicemailSettings=" + mSubMenuVoicemailSettings);
1157 }
1158 if (mSubMenuVoicemailSettings == null) {
1159 return;
1160 }
1161
1162 mOldVmNumber = mPhone.getVoiceMailNumber();
1163 if (mOldVmNumber == null) {
1164 mOldVmNumber = "";
1165 }
1166 mSubMenuVoicemailSettings.setPhoneNumber(mOldVmNumber);
1167 final String summary = (mOldVmNumber.length() > 0) ? mOldVmNumber :
1168 getString(R.string.voicemail_number_not_set);
1169 mSubMenuVoicemailSettings.setSummary(summary);
1170 }
1171
1172 /*
1173 * Helper Methods for Activity class.
1174 * The initial query commands are split into two pieces now
1175 * for individual expansion. This combined with the ability
1176 * to cancel queries allows for a much better user experience,
1177 * and also ensures that the user only waits to update the
1178 * data that is relevant.
1179 */
1180
1181 @Override
1182 protected void onPrepareDialog(int id, Dialog dialog) {
1183 super.onPrepareDialog(id, dialog);
1184 mCurrentDialogId = id;
1185 }
1186
1187 // dialog creation method, called by showDialog()
1188 @Override
1189 protected Dialog onCreateDialog(int id) {
1190 if ((id == VM_RESPONSE_ERROR) || (id == VM_NOCHANGE_ERROR) ||
1191 (id == FW_SET_RESPONSE_ERROR) || (id == FW_GET_RESPONSE_ERROR) ||
1192 (id == VOICEMAIL_DIALOG_CONFIRM)) {
1193
1194 AlertDialog.Builder b = new AlertDialog.Builder(this);
1195
1196 int msgId;
1197 int titleId = R.string.error_updating_title;
1198 switch (id) {
1199 case VOICEMAIL_DIALOG_CONFIRM:
1200 msgId = R.string.vm_changed;
1201 titleId = R.string.voicemail;
1202 // Set Button 2
1203 b.setNegativeButton(R.string.close_dialog, this);
1204 break;
1205 case VM_NOCHANGE_ERROR:
1206 // even though this is technically an error,
1207 // keep the title friendly.
1208 msgId = R.string.no_change;
1209 titleId = R.string.voicemail;
1210 // Set Button 2
1211 b.setNegativeButton(R.string.close_dialog, this);
1212 break;
1213 case VM_RESPONSE_ERROR:
1214 msgId = R.string.vm_change_failed;
1215 // Set Button 1
1216 b.setPositiveButton(R.string.close_dialog, this);
1217 break;
1218 case FW_SET_RESPONSE_ERROR:
1219 msgId = R.string.fw_change_failed;
1220 // Set Button 1
1221 b.setPositiveButton(R.string.close_dialog, this);
1222 break;
1223 case FW_GET_RESPONSE_ERROR:
1224 msgId = R.string.fw_get_in_vm_failed;
1225 b.setPositiveButton(R.string.alert_dialog_yes, this);
1226 b.setNegativeButton(R.string.alert_dialog_no, this);
1227 break;
1228 default:
1229 msgId = R.string.exception_error;
1230 // Set Button 3, tells the activity that the error is
1231 // not recoverable on dialog exit.
1232 b.setNeutralButton(R.string.close_dialog, this);
1233 break;
1234 }
1235
1236 b.setTitle(getText(titleId));
1237 String message = getText(msgId).toString();
1238 b.setMessage(message);
1239 b.setCancelable(false);
1240 AlertDialog dialog = b.create();
1241
1242 // make the dialog more obvious by bluring the background.
1243 dialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
1244
1245 return dialog;
1246 } else if (id == VOICEMAIL_FWD_SAVING_DIALOG || id == VOICEMAIL_FWD_READING_DIALOG ||
1247 id == VOICEMAIL_REVERTING_DIALOG) {
1248 ProgressDialog dialog = new ProgressDialog(this);
Andrew Lee5ed870c2014-10-29 11:47:49 -07001249 dialog.setTitle(getText(R.string.call_settings));
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001250 dialog.setIndeterminate(true);
1251 dialog.setCancelable(false);
1252 dialog.setMessage(getText(
1253 id == VOICEMAIL_FWD_SAVING_DIALOG ? R.string.updating_settings :
1254 (id == VOICEMAIL_REVERTING_DIALOG ? R.string.reverting_settings :
1255 R.string.reading_settings)));
1256 return dialog;
1257 }
1258
1259
1260 return null;
1261 }
1262
1263 // This is a method implemented for DialogInterface.OnClickListener.
1264 // Used with the error dialog to close the app, voicemail dialog to just dismiss.
1265 // Close button is mapped to BUTTON_POSITIVE for the errors that close the activity,
1266 // while those that are mapped to BUTTON_NEUTRAL only move the preference focus.
1267 public void onClick(DialogInterface dialog, int which) {
1268 dialog.dismiss();
1269 switch (which){
1270 case DialogInterface.BUTTON_NEUTRAL:
1271 if (DBG) log("Neutral button");
1272 break;
1273 case DialogInterface.BUTTON_NEGATIVE:
1274 if (DBG) log("Negative button");
1275 if (mCurrentDialogId == FW_GET_RESPONSE_ERROR) {
1276 // We failed to get current forwarding settings and the user
1277 // does not wish to continue.
1278 switchToPreviousVoicemailProvider();
1279 }
1280 break;
1281 case DialogInterface.BUTTON_POSITIVE:
1282 if (DBG) log("Positive button");
1283 if (mCurrentDialogId == FW_GET_RESPONSE_ERROR) {
1284 // We failed to get current forwarding settings but the user
1285 // wishes to continue changing settings to the new vm provider
1286 saveVoiceMailAndForwardingNumberStage2();
1287 } else {
1288 finish();
1289 }
1290 return;
1291 default:
1292 // just let the dialog close and go back to the input
1293 }
1294 // In all dialogs, all buttons except BUTTON_POSITIVE lead to the end of user interaction
1295 // with settings UI. If we were called to explicitly configure voice mail then
1296 // we finish the settings activity here to come back to whatever the user was doing.
1297 if (getIntent().getAction().equals(ACTION_ADD_VOICEMAIL)) {
1298 finish();
1299 }
1300 }
1301
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001302 /*
1303 * Activity class methods
1304 */
1305
1306 @Override
1307 protected void onCreate(Bundle icicle) {
1308 super.onCreate(icicle);
1309 if (DBG) log("onCreate(). Intent: " + getIntent());
1310 mPhone = PhoneGlobals.getPhone();
Tyler Gunnbaee2952014-09-10 16:01:02 -07001311 mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
Andrew Lee88b51e22014-10-29 15:48:51 -07001312 mVmProviderSettingsUtil = new VoicemailProviderSettingsUtil(getApplicationContext());
Tyler Gunnbaee2952014-09-10 16:01:02 -07001313
Tyler Gunnbaee2952014-09-10 16:01:02 -07001314 // Show the voicemail preference in onResume if the calling intent specifies the
1315 // ACTION_ADD_VOICEMAIL action.
1316 mShowVoicemailPreference = (icicle == null) &&
1317 getIntent().getAction().equals(ACTION_ADD_VOICEMAIL);
Andrew Lee5ed870c2014-10-29 11:47:49 -07001318
1319 mSubscriptionInfoHelper = new SubscriptionInfoHelper(getIntent());
1320 mSubscriptionInfoHelper.setActionBarTitle(
1321 getActionBar(), getResources(), R.string.call_settings_with_label);
1322 }
Tyler Gunnbaee2952014-09-10 16:01:02 -07001323
1324 private void initPhoneAccountPreferences() {
Andrew Leece8ae2a2014-09-10 10:41:48 -07001325 mPhoneAccountSettingsPreference = findPreference(PHONE_ACCOUNT_SETTINGS_KEY);
Tyler Gunnbaee2952014-09-10 16:01:02 -07001326
Tyler Gunn4d45d1c2014-09-12 22:17:53 -07001327 TelecomManager telecomManager = TelecomManager.from(this);
Andrew Lee93c345f2014-10-27 15:25:07 -07001328 TelephonyManager telephonyManager =
1329 (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
Tyler Gunnbaee2952014-09-10 16:01:02 -07001330
Andrew Lee93c345f2014-10-27 15:25:07 -07001331 if ((telecomManager.getSimCallManagers().isEmpty() && !SipUtil.isVoipSupported(this))
1332 || telephonyManager.getPhoneCount() > 1) {
Andrew Leece8ae2a2014-09-10 10:41:48 -07001333 getPreferenceScreen().removePreference(mPhoneAccountSettingsPreference);
Tyler Gunnbaee2952014-09-10 16:01:02 -07001334 }
1335 }
1336
1337 private boolean canLaunchIntent(Intent intent) {
1338 PackageManager pm = getPackageManager();
1339 return pm.resolveActivity(intent, PackageManager.GET_ACTIVITIES) != null;
1340 }
1341
Tyler Gunnbaee2952014-09-10 16:01:02 -07001342 @Override
1343 protected void onResume() {
1344 super.onResume();
1345 mForeground = true;
1346
1347 PreferenceScreen preferenceScreen = getPreferenceScreen();
1348 if (preferenceScreen != null) {
1349 preferenceScreen.removeAll();
1350 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001351
1352 addPreferencesFromResource(R.xml.call_feature_setting);
Andrew Lee5ed870c2014-10-29 11:47:49 -07001353
Andrew Leedb2fe562014-09-03 15:40:43 -07001354 initPhoneAccountPreferences();
1355
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001356 PreferenceScreen prefSet = getPreferenceScreen();
Andrew Lee64a7d792014-10-15 17:38:38 -07001357 mSubMenuVoicemailSettings = (EditPhoneNumberPreference) findPreference(BUTTON_VOICEMAIL_KEY);
1358 mSubMenuVoicemailSettings.setParentActivity(this, VOICEMAIL_PREF_ID, this);
1359 mSubMenuVoicemailSettings.setDialogOnClosedListener(this);
1360 mSubMenuVoicemailSettings.setDialogTitle(R.string.voicemail_settings_number_label);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001361
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001362 mButtonDTMF = (ListPreference) findPreference(BUTTON_DTMF_KEY);
1363 mButtonAutoRetry = (CheckBoxPreference) findPreference(BUTTON_RETRY_KEY);
1364 mButtonHAC = (CheckBoxPreference) findPreference(BUTTON_HAC_KEY);
1365 mButtonTTY = (ListPreference) findPreference(BUTTON_TTY_KEY);
1366 mVoicemailProviders = (ListPreference) findPreference(BUTTON_VOICEMAIL_PROVIDER_KEY);
Andrew Lee312e8172014-10-23 17:01:36 -07001367 mEnableVideoCalling = (CheckBoxPreference) findPreference(ENABLE_VIDEO_CALLING_KEY);
Andrew Lee2170a972014-08-13 18:13:01 -07001368
Andrew Lee2c027892014-10-29 11:29:54 -07001369 mVoicemailProviders.setOnPreferenceChangeListener(this);
1370 mVoicemailSettingsScreen =
1371 (PreferenceScreen) findPreference(VOICEMAIL_SETTING_SCREEN_PREF_KEY);
1372 mVoicemailSettings = (PreferenceScreen)findPreference(BUTTON_VOICEMAIL_SETTING_KEY);
1373 mVoicemailNotificationVibrate =
1374 (CheckBoxPreference) findPreference(BUTTON_VOICEMAIL_NOTIFICATION_VIBRATE_KEY);
1375 initVoiceMailProviders();
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001376
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001377
Andrew Lee64a7d792014-10-15 17:38:38 -07001378 if (getResources().getBoolean(R.bool.dtmf_type_enabled)) {
1379 mButtonDTMF.setOnPreferenceChangeListener(this);
1380 int dtmf = Settings.System.getInt(getContentResolver(),
1381 Settings.System.DTMF_TONE_TYPE_WHEN_DIALING, Constants.DTMF_TONE_TYPE_NORMAL);
1382 mButtonDTMF.setValueIndex(dtmf);
1383 } else {
1384 prefSet.removePreference(mButtonDTMF);
1385 mButtonDTMF = null;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001386 }
1387
Andrew Lee64a7d792014-10-15 17:38:38 -07001388 if (getResources().getBoolean(R.bool.auto_retry_enabled)) {
1389 mButtonAutoRetry.setOnPreferenceChangeListener(this);
1390 int autoretry = Settings.Global.getInt(
1391 getContentResolver(), Settings.Global.CALL_AUTO_RETRY, 0);
1392 mButtonAutoRetry.setChecked(autoretry != 0);
1393 } else {
1394 prefSet.removePreference(mButtonAutoRetry);
1395 mButtonAutoRetry = null;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001396 }
1397
Andrew Lee64a7d792014-10-15 17:38:38 -07001398 if (getResources().getBoolean(R.bool.hac_enabled)) {
1399 mButtonHAC.setOnPreferenceChangeListener(this);
1400 int hac = Settings.System.getInt(getContentResolver(), Settings.System.HEARING_AID, 0);
1401 mButtonHAC.setChecked(hac != 0);
1402 } else {
1403 prefSet.removePreference(mButtonHAC);
1404 mButtonHAC = null;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001405 }
1406
Andrew Lee64a7d792014-10-15 17:38:38 -07001407 TelecomManager telecomManager = TelecomManager.from(this);
1408 if (telecomManager != null && telecomManager.isTtySupported()) {
1409 mButtonTTY.setOnPreferenceChangeListener(this);
1410 int settingsTtyMode = Settings.Secure.getInt(getContentResolver(),
1411 Settings.Secure.PREFERRED_TTY_MODE,
1412 TelecomManager.TTY_MODE_OFF);
1413 mButtonTTY.setValue(Integer.toString(settingsTtyMode));
1414 updatePreferredTtyModeSummary(settingsTtyMode);
1415 } else {
1416 prefSet.removePreference(mButtonTTY);
1417 mButtonTTY = null;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001418 }
1419
1420 if (!getResources().getBoolean(R.bool.world_phone)) {
1421 Preference options = prefSet.findPreference(BUTTON_CDMA_OPTIONS);
Andrew Lee2170a972014-08-13 18:13:01 -07001422 if (options != null) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001423 prefSet.removePreference(options);
Andrew Lee2170a972014-08-13 18:13:01 -07001424 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001425 options = prefSet.findPreference(BUTTON_GSM_UMTS_OPTIONS);
Andrew Lee2170a972014-08-13 18:13:01 -07001426 if (options != null) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001427 prefSet.removePreference(options);
Andrew Lee2170a972014-08-13 18:13:01 -07001428 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001429
1430 int phoneType = mPhone.getPhoneType();
Andrew Lee5ed870c2014-10-29 11:47:49 -07001431 Preference fdnButton = prefSet.findPreference(BUTTON_FDN_KEY);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001432 if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) {
Andrew Lee5ed870c2014-10-29 11:47:49 -07001433 prefSet.removePreference(fdnButton);
1434
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001435 if (!getResources().getBoolean(R.bool.config_voice_privacy_disable)) {
1436 addPreferencesFromResource(R.xml.cdma_call_privacy);
1437 }
1438 } else if (phoneType == PhoneConstants.PHONE_TYPE_GSM) {
Andrew Lee5ed870c2014-10-29 11:47:49 -07001439 fdnButton.setIntent(mSubscriptionInfoHelper.getIntent(this, FdnSetting.class));
1440
Andrew Lee2170a972014-08-13 18:13:01 -07001441 if (getResources().getBoolean(R.bool.config_additional_call_setting)) {
Etan Cohen0ca1c802014-07-07 15:35:48 -07001442 addPreferencesFromResource(R.xml.gsm_umts_call_options);
1443 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001444 } else {
1445 throw new IllegalStateException("Unexpected phone type: " + phoneType);
1446 }
1447 }
1448
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001449 // check the intent that started this activity and pop up the voicemail
1450 // dialog if we've been asked to.
1451 // If we have at least one non default VM provider registered then bring up
1452 // the selection for the VM provider, otherwise bring up a VM number dialog.
1453 // We only bring up the dialog the first time we are called (not after orientation change)
Andrew Lee2c027892014-10-29 11:29:54 -07001454 if (mShowVoicemailPreference) {
Tyler Gunnbaee2952014-09-10 16:01:02 -07001455 if (DBG) {
1456 log("ACTION_ADD_VOICEMAIL Intent is thrown. current VM data size: "
1457 + mVMProvidersData.size());
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001458 }
Tyler Gunnbaee2952014-09-10 16:01:02 -07001459 if (mVMProvidersData.size() > 1) {
1460 simulatePreferenceClick(mVoicemailProviders);
1461 } else {
1462 onPreferenceChange(mVoicemailProviders, DEFAULT_VM_PROVIDER_KEY);
1463 mVoicemailProviders.setValue(DEFAULT_VM_PROVIDER_KEY);
1464 }
1465 mShowVoicemailPreference = false;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001466 }
Tyler Gunnbaee2952014-09-10 16:01:02 -07001467
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001468 updateVoiceNumberField();
1469 mVMProviderSettingsForced = false;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001470
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001471 SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(
1472 mPhone.getContext());
1473 if (migrateVoicemailVibrationSettingsIfNeeded(prefs)) {
1474 mVoicemailNotificationVibrate.setChecked(prefs.getBoolean(
1475 BUTTON_VOICEMAIL_NOTIFICATION_VIBRATE_KEY, false));
1476 }
1477
Andrew Lee312e8172014-10-23 17:01:36 -07001478 if (ImsManager.isVtEnabledByPlatform(mPhone.getContext()) && ENABLE_VT_FLAG) {
1479 boolean currentValue =
1480 ImsManager.isEnhanced4gLteModeSettingEnabledByUser(mPhone.getContext())
1481 ? PhoneGlobals.getInstance().phoneMgr.isVideoCallingEnabled() : false;
1482 mEnableVideoCalling.setChecked(currentValue);
Andrew Lee77527ac2014-10-21 16:57:39 -07001483 mEnableVideoCalling.setOnPreferenceChangeListener(this);
1484 } else {
1485 prefSet.removePreference(mEnableVideoCalling);
1486 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001487 }
1488
1489 // Migrate settings from BUTTON_VOICEMAIL_NOTIFICATION_VIBRATE_WHEN_KEY to
1490 // BUTTON_VOICEMAIL_NOTIFICATION_VIBRATE_KEY, if the latter does not exist.
1491 // Returns true if migration was performed.
1492 public static boolean migrateVoicemailVibrationSettingsIfNeeded(SharedPreferences prefs) {
1493 if (!prefs.contains(BUTTON_VOICEMAIL_NOTIFICATION_VIBRATE_KEY)) {
1494 String vibrateWhen = prefs.getString(
1495 BUTTON_VOICEMAIL_NOTIFICATION_VIBRATE_WHEN_KEY, VOICEMAIL_VIBRATION_NEVER);
1496 // If vibrateWhen is always, then voicemailVibrate should be True.
1497 // otherwise if vibrateWhen is "only in silent mode", or "never", then
1498 // voicemailVibrate = False.
1499 boolean voicemailVibrate = vibrateWhen.equals(VOICEMAIL_VIBRATION_ALWAYS);
1500 final SharedPreferences.Editor editor = prefs.edit();
1501 editor.putBoolean(BUTTON_VOICEMAIL_NOTIFICATION_VIBRATE_KEY, voicemailVibrate);
1502 editor.commit();
1503 return true;
1504 }
1505 return false;
1506 }
1507
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001508 private void handleTTYChange(Preference preference, Object objValue) {
1509 int buttonTtyMode;
1510 buttonTtyMode = Integer.valueOf((String) objValue).intValue();
1511 int settingsTtyMode = android.provider.Settings.Secure.getInt(
1512 getContentResolver(),
Sailesh Nepalbf900542014-07-15 16:18:32 -07001513 android.provider.Settings.Secure.PREFERRED_TTY_MODE,
Tyler Gunn4d45d1c2014-09-12 22:17:53 -07001514 TelecomManager.TTY_MODE_OFF);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001515 if (DBG) log("handleTTYChange: requesting set TTY mode enable (TTY) to" +
1516 Integer.toString(buttonTtyMode));
1517
1518 if (buttonTtyMode != settingsTtyMode) {
1519 switch(buttonTtyMode) {
Tyler Gunn4d45d1c2014-09-12 22:17:53 -07001520 case TelecomManager.TTY_MODE_OFF:
1521 case TelecomManager.TTY_MODE_FULL:
1522 case TelecomManager.TTY_MODE_HCO:
1523 case TelecomManager.TTY_MODE_VCO:
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001524 android.provider.Settings.Secure.putInt(getContentResolver(),
1525 android.provider.Settings.Secure.PREFERRED_TTY_MODE, buttonTtyMode);
1526 break;
1527 default:
Tyler Gunn4d45d1c2014-09-12 22:17:53 -07001528 buttonTtyMode = TelecomManager.TTY_MODE_OFF;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001529 }
1530
1531 mButtonTTY.setValue(Integer.toString(buttonTtyMode));
1532 updatePreferredTtyModeSummary(buttonTtyMode);
Tyler Gunn4d45d1c2014-09-12 22:17:53 -07001533 Intent ttyModeChanged = new Intent(TelecomManager.ACTION_TTY_PREFERRED_MODE_CHANGED);
1534 ttyModeChanged.putExtra(TelecomManager.EXTRA_TTY_PREFERRED_MODE, buttonTtyMode);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001535 sendBroadcastAsUser(ttyModeChanged, UserHandle.ALL);
1536 }
1537 }
1538
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001539 private void updatePreferredTtyModeSummary(int TtyMode) {
1540 String [] txts = getResources().getStringArray(R.array.tty_mode_entries);
1541 switch(TtyMode) {
Tyler Gunn4d45d1c2014-09-12 22:17:53 -07001542 case TelecomManager.TTY_MODE_OFF:
1543 case TelecomManager.TTY_MODE_HCO:
1544 case TelecomManager.TTY_MODE_VCO:
1545 case TelecomManager.TTY_MODE_FULL:
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001546 mButtonTTY.setSummary(txts[TtyMode]);
1547 break;
1548 default:
1549 mButtonTTY.setEnabled(false);
Tyler Gunn4d45d1c2014-09-12 22:17:53 -07001550 mButtonTTY.setSummary(txts[TelecomManager.TTY_MODE_OFF]);
Sailesh Nepalbf900542014-07-15 16:18:32 -07001551 break;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001552 }
1553 }
1554
1555 private static void log(String msg) {
1556 Log.d(LOG_TAG, msg);
1557 }
1558
1559 /**
1560 * Updates the look of the VM preference widgets based on current VM provider settings.
1561 * Note that the provider name is loaded form the found activity via loadLabel in
1562 * {@link #initVoiceMailProviders()} in order for it to be localizable.
1563 */
1564 private void updateVMPreferenceWidgets(String currentProviderSetting) {
1565 final String key = currentProviderSetting;
1566 final VoiceMailProvider provider = mVMProvidersData.get(key);
1567
1568 /* This is the case when we are coming up on a freshly wiped phone and there is no
1569 persisted value for the list preference mVoicemailProviders.
1570 In this case we want to show the UI asking the user to select a voicemail provider as
1571 opposed to silently falling back to default one. */
1572 if (provider == null) {
1573 if (DBG) {
1574 log("updateVMPreferenceWidget: provider for the key \"" + key + "\" is null.");
1575 }
1576 mVoicemailProviders.setSummary(getString(R.string.sum_voicemail_choose_provider));
1577 mVoicemailSettings.setEnabled(false);
1578 mVoicemailSettings.setIntent(null);
1579
1580 mVoicemailNotificationVibrate.setEnabled(false);
1581 } else {
1582 if (DBG) {
1583 log("updateVMPreferenceWidget: provider for the key \"" + key + "\".."
1584 + "name: " + provider.name
1585 + ", intent: " + provider.intent);
1586 }
1587 final String providerName = provider.name;
1588 mVoicemailProviders.setSummary(providerName);
1589 mVoicemailSettings.setEnabled(true);
1590 mVoicemailSettings.setIntent(provider.intent);
1591
1592 mVoicemailNotificationVibrate.setEnabled(true);
1593 }
1594 }
1595
1596 /**
1597 * Enumerates existing VM providers and puts their data into the list and populates
1598 * the preference list objects with their names.
1599 * In case we are called with ACTION_ADD_VOICEMAIL intent the intent may have
1600 * an extra string called IGNORE_PROVIDER_EXTRA with "package.activityName" of the provider
1601 * which should be hidden when we bring up the list of possible VM providers to choose.
1602 */
1603 private void initVoiceMailProviders() {
1604 if (DBG) log("initVoiceMailProviders()");
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001605
1606 String providerToIgnore = null;
1607 if (getIntent().getAction().equals(ACTION_ADD_VOICEMAIL)) {
1608 if (getIntent().hasExtra(IGNORE_PROVIDER_EXTRA)) {
1609 providerToIgnore = getIntent().getStringExtra(IGNORE_PROVIDER_EXTRA);
1610 }
1611 if (DBG) log("Found ACTION_ADD_VOICEMAIL. providerToIgnore=" + providerToIgnore);
1612 if (providerToIgnore != null) {
1613 // IGNORE_PROVIDER_EXTRA implies we want to remove the choice from the list.
Andrew Lee88b51e22014-10-29 15:48:51 -07001614 mVmProviderSettingsUtil.delete(providerToIgnore);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001615 }
1616 }
1617
1618 mVMProvidersData.clear();
1619
1620 // Stick the default element which is always there
1621 final String myCarrier = getString(R.string.voicemail_default);
1622 mVMProvidersData.put(DEFAULT_VM_PROVIDER_KEY, new VoiceMailProvider(myCarrier, null));
1623
1624 // Enumerate providers
1625 PackageManager pm = getPackageManager();
1626 Intent intent = new Intent();
1627 intent.setAction(ACTION_CONFIGURE_VOICEMAIL);
1628 List<ResolveInfo> resolveInfos = pm.queryIntentActivities(intent, 0);
1629 int len = resolveInfos.size() + 1; // +1 for the default choice we will insert.
1630
1631 // Go through the list of discovered providers populating the data map
1632 // skip the provider we were instructed to ignore if there was one
1633 for (int i = 0; i < resolveInfos.size(); i++) {
1634 final ResolveInfo ri= resolveInfos.get(i);
1635 final ActivityInfo currentActivityInfo = ri.activityInfo;
Andrew Lee6214e2b2014-11-04 13:57:38 -08001636 final String key = currentActivityInfo.name;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001637 if (key.equals(providerToIgnore)) {
1638 if (DBG) log("Ignoring key: " + key);
1639 len--;
1640 continue;
1641 }
1642 if (DBG) log("Loading key: " + key);
1643 final String nameForDisplay = ri.loadLabel(pm).toString();
1644 Intent providerIntent = new Intent();
1645 providerIntent.setAction(ACTION_CONFIGURE_VOICEMAIL);
1646 providerIntent.setClassName(currentActivityInfo.packageName,
1647 currentActivityInfo.name);
1648 if (DBG) {
1649 log("Store loaded VoiceMailProvider. key: " + key
1650 + " -> name: " + nameForDisplay + ", intent: " + providerIntent);
1651 }
1652 mVMProvidersData.put(
1653 key,
1654 new VoiceMailProvider(nameForDisplay, providerIntent));
1655
1656 }
1657
1658 // Now we know which providers to display - create entries and values array for
1659 // the list preference
1660 String [] entries = new String [len];
1661 String [] values = new String [len];
1662 entries[0] = myCarrier;
1663 values[0] = DEFAULT_VM_PROVIDER_KEY;
1664 int entryIdx = 1;
1665 for (int i = 0; i < resolveInfos.size(); i++) {
Andrew Lee6214e2b2014-11-04 13:57:38 -08001666 final String key = resolveInfos.get(i).activityInfo.name;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001667 if (!mVMProvidersData.containsKey(key)) {
1668 continue;
1669 }
1670 entries[entryIdx] = mVMProvidersData.get(key).name;
1671 values[entryIdx] = key;
1672 entryIdx++;
1673 }
1674
1675 // ListPreference is now updated.
1676 mVoicemailProviders.setEntries(entries);
1677 mVoicemailProviders.setEntryValues(values);
1678
1679 // Remember the current Voicemail Provider key as a "previous" key. This will be used
1680 // when we fail to update Voicemail Provider, which requires rollback.
1681 // We will update this when the VM Provider setting is successfully updated.
1682 mPreviousVMProviderKey = getCurrentVoicemailProviderKey();
1683 if (DBG) log("Set up the first mPreviousVMProviderKey: " + mPreviousVMProviderKey);
1684
1685 // Finally update the preference texts.
1686 updateVMPreferenceWidgets(mPreviousVMProviderKey);
1687 }
1688
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001689 /**
1690 * Simulates user clicking on a passed preference.
1691 * Usually needed when the preference is a dialog preference and we want to invoke
1692 * a dialog for this preference programmatically.
Santos Cordonda120f42014-08-06 04:44:34 -07001693 * TODO: figure out if there is a cleaner way to cause preference dlg to come up
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001694 */
1695 private void simulatePreferenceClick(Preference preference) {
1696 // Go through settings until we find our setting
1697 // and then simulate a click on it to bring up the dialog
1698 final ListAdapter adapter = getPreferenceScreen().getRootAdapter();
1699 for (int idx = 0; idx < adapter.getCount(); idx++) {
1700 if (adapter.getItem(idx) == preference) {
1701 getPreferenceScreen().onItemClick(this.getListView(),
1702 null, idx, adapter.getItemId(idx));
1703 break;
1704 }
1705 }
1706 }
1707
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001708 private String getCurrentVoicemailProviderKey() {
1709 final String key = mVoicemailProviders.getValue();
1710 return (key != null) ? key : DEFAULT_VM_PROVIDER_KEY;
1711 }
1712
1713 @Override
1714 public boolean onOptionsItemSelected(MenuItem item) {
1715 final int itemId = item.getItemId();
1716 if (itemId == android.R.id.home) { // See ActionBar#setDisplayHomeAsUpEnabled()
Yorke Leef2d0cac2013-09-09 19:42:56 -07001717 onBackPressed();
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001718 return true;
1719 }
1720 return super.onOptionsItemSelected(item);
1721 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001722 /**
1723 * Finish current Activity and go up to the top level Settings ({@link CallFeaturesSetting}).
1724 * This is useful for implementing "HomeAsUp" capability for second-level Settings.
1725 */
1726 public static void goUpToTopLevelSetting(Activity activity) {
1727 Intent intent = new Intent(activity, CallFeaturesSetting.class);
1728 intent.setAction(Intent.ACTION_MAIN);
1729 intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
1730 activity.startActivity(intent);
1731 activity.finish();
1732 }
1733}