1/* 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; 21import android.app.ActivityOptions; 22import android.app.AlertDialog; 23import android.app.Dialog; 24import android.content.ContentResolver; 25import android.content.Context; 26import android.content.DialogInterface; 27import android.content.Intent; 28import android.content.pm.PackageManager; 29import android.content.pm.ResolveInfo; 30import android.os.Bundle; 31import android.os.PersistableBundle; 32import android.os.UserHandle; 33import android.os.UserManager; 34import android.preference.CheckBoxPreference; 35import android.preference.ListPreference; 36import android.preference.Preference; 37import android.preference.PreferenceActivity; 38import android.preference.PreferenceScreen; 39import android.provider.Settings; 40import android.telecom.PhoneAccountHandle; 41import android.telecom.TelecomManager; 42import android.telephony.CarrierConfigManager; 43import android.telephony.PhoneStateListener; 44import android.telephony.TelephonyManager; 45import android.text.TextUtils; 46import android.util.Log; 47import android.view.MenuItem; 48import android.widget.Toast; 49 50import com.android.ims.ImsConfig; 51import com.android.ims.ImsManager; 52import com.android.internal.telephony.CallForwardInfo; 53import com.android.internal.telephony.Phone; 54import com.android.internal.telephony.PhoneConstants; 55import com.android.phone.common.util.SettingsUtil; 56import com.android.phone.settings.AccountSelectionPreference; 57import com.android.phone.settings.PhoneAccountSettingsFragment; 58import com.android.phone.settings.VoicemailSettingsActivity; 59import com.android.phone.settings.fdn.FdnSetting; 60import com.android.services.telephony.sip.SipUtil; 61 62import java.lang.String; 63import java.util.ArrayList; 64import java.util.List; 65 66/** 67 * Top level "Call settings" UI; see res/xml/call_feature_setting.xml 68 * 69 * This preference screen is the root of the "Call settings" hierarchy available from the Phone 70 * app; the settings here let you control various features related to phone calls (including 71 * voicemail settings, the "Respond via SMS" feature, and others.) It's used only on 72 * voice-capable phone devices. 73 * 74 * Note that this activity is part of the package com.android.phone, even 75 * though you reach it from the "Phone" app (i.e. DialtactsActivity) which 76 * is from the package com.android.contacts. 77 * 78 * For the "Mobile network settings" screen under the main Settings app, 79 * See {@link MobileNetworkSettings}. 80 * 81 * @see com.android.phone.MobileNetworkSettings 82 */ 83public class CallFeaturesSetting extends PreferenceActivity 84 implements Preference.OnPreferenceChangeListener { 85 private static final String LOG_TAG = "CallFeaturesSetting"; 86 private static final boolean DBG = (PhoneGlobals.DBG_LEVEL >= 2); 87 88 // String keys for preference lookup 89 // TODO: Naming these "BUTTON_*" is confusing since they're not actually buttons(!) 90 // TODO: Consider moving these strings to strings.xml, so that they are not duplicated here and 91 // in the layout files. These strings need to be treated carefully; if the setting is 92 // persistent, they are used as the key to store shared preferences and the name should not be 93 // changed unless the settings are also migrated. 94 private static final String VOICEMAIL_SETTING_SCREEN_PREF_KEY = "button_voicemail_category_key"; 95 private static final String BUTTON_FDN_KEY = "button_fdn_key"; 96 private static final String BUTTON_RETRY_KEY = "button_auto_retry_key"; 97 private static final String BUTTON_GSM_UMTS_OPTIONS = "button_gsm_more_expand_key"; 98 private static final String BUTTON_CDMA_OPTIONS = "button_cdma_more_expand_key"; 99 100 private static final String PHONE_ACCOUNT_SETTINGS_KEY = 101 "phone_account_settings_preference_screen"; 102 103 private static final String ENABLE_VIDEO_CALLING_KEY = "button_enable_video_calling"; 104 105 private Phone mPhone; 106 private SubscriptionInfoHelper mSubscriptionInfoHelper; 107 private TelecomManager mTelecomManager; 108 109 private CheckBoxPreference mButtonAutoRetry; 110 private PreferenceScreen mVoicemailSettingsScreen; 111 private CheckBoxPreference mEnableVideoCalling; 112 113 /* 114 * Click Listeners, handle click based on objects attached to UI. 115 */ 116 117 // Click listener for all toggle events 118 @Override 119 public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) { 120 if (preference == mButtonAutoRetry) { 121 android.provider.Settings.Global.putInt(mPhone.getContext().getContentResolver(), 122 android.provider.Settings.Global.CALL_AUTO_RETRY, 123 mButtonAutoRetry.isChecked() ? 1 : 0); 124 return true; 125 } 126 return false; 127 } 128 129 /** 130 * Implemented to support onPreferenceChangeListener to look for preference 131 * changes. 132 * 133 * @param preference is the preference to be changed 134 * @param objValue should be the value of the selection, NOT its localized 135 * display value. 136 */ 137 @Override 138 public boolean onPreferenceChange(Preference preference, Object objValue) { 139 if (DBG) log("onPreferenceChange: \"" + preference + "\" changed to \"" + objValue + "\""); 140 141 if (preference == mEnableVideoCalling) { 142 if (ImsManager.isEnhanced4gLteModeSettingEnabledByUser(mPhone.getContext())) { 143 PhoneGlobals.getInstance().phoneMgr.enableVideoCalling((boolean) objValue); 144 } else { 145 AlertDialog.Builder builder = new AlertDialog.Builder(this); 146 DialogInterface.OnClickListener networkSettingsClickListener = 147 new Dialog.OnClickListener() { 148 @Override 149 public void onClick(DialogInterface dialog, int which) { 150 startActivity(new Intent(mPhone.getContext(), 151 com.android.phone.MobileNetworkSettings.class)); 152 } 153 }; 154 builder.setMessage(getResources().getString( 155 R.string.enable_video_calling_dialog_msg)) 156 .setNeutralButton(getResources().getString( 157 R.string.enable_video_calling_dialog_settings), 158 networkSettingsClickListener) 159 .setPositiveButton(android.R.string.ok, null) 160 .show(); 161 return false; 162 } 163 } 164 165 // Always let the preference setting proceed. 166 return true; 167 } 168 169 @Override 170 protected void onCreate(Bundle icicle) { 171 super.onCreate(icicle); 172 if (DBG) log("onCreate: Intent is " + getIntent()); 173 174 // Make sure we are running as an admin user. 175 if (!UserManager.get(this).isAdminUser()) { 176 Toast.makeText(this, R.string.call_settings_admin_user_only, 177 Toast.LENGTH_SHORT).show(); 178 finish(); 179 return; 180 } 181 182 mSubscriptionInfoHelper = new SubscriptionInfoHelper(this, getIntent()); 183 mSubscriptionInfoHelper.setActionBarTitle( 184 getActionBar(), getResources(), R.string.call_settings_with_label); 185 mPhone = mSubscriptionInfoHelper.getPhone(); 186 mTelecomManager = TelecomManager.from(this); 187 } 188 189 private final PhoneStateListener mPhoneStateListener = new PhoneStateListener() { 190 @Override 191 public void onCallStateChanged(int state, String incomingNumber) { 192 if (DBG) log("PhoneStateListener onCallStateChanged: state is " + state); 193 if (mEnableVideoCalling != null) { 194 mEnableVideoCalling.setEnabled(state == TelephonyManager.CALL_STATE_IDLE); 195 } 196 } 197 }; 198 199 @Override 200 protected void onPause() { 201 super.onPause(); 202 TelephonyManager telephonyManager = 203 (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE); 204 telephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE); 205 } 206 207 @Override 208 protected void onResume() { 209 super.onResume(); 210 211 PreferenceScreen preferenceScreen = getPreferenceScreen(); 212 if (preferenceScreen != null) { 213 preferenceScreen.removeAll(); 214 } 215 216 addPreferencesFromResource(R.xml.call_feature_setting); 217 218 TelephonyManager telephonyManager = 219 (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE); 220 telephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_CALL_STATE); 221 222 Preference phoneAccountSettingsPreference = findPreference(PHONE_ACCOUNT_SETTINGS_KEY); 223 if (telephonyManager.isMultiSimEnabled() || !SipUtil.isVoipSupported(mPhone.getContext())) { 224 getPreferenceScreen().removePreference(phoneAccountSettingsPreference); 225 } 226 227 PreferenceScreen prefSet = getPreferenceScreen(); 228 mVoicemailSettingsScreen = 229 (PreferenceScreen) findPreference(VOICEMAIL_SETTING_SCREEN_PREF_KEY); 230 mVoicemailSettingsScreen.setIntent(mSubscriptionInfoHelper.getIntent( 231 VoicemailSettingsActivity.class)); 232 233 mButtonAutoRetry = (CheckBoxPreference) findPreference(BUTTON_RETRY_KEY); 234 235 mEnableVideoCalling = (CheckBoxPreference) findPreference(ENABLE_VIDEO_CALLING_KEY); 236 237 PersistableBundle carrierConfig = 238 PhoneGlobals.getInstance().getCarrierConfigForSubId(mPhone.getSubId()); 239 240 if (carrierConfig.getBoolean(CarrierConfigManager.KEY_AUTO_RETRY_ENABLED_BOOL)) { 241 mButtonAutoRetry.setOnPreferenceChangeListener(this); 242 int autoretry = Settings.Global.getInt( 243 getContentResolver(), Settings.Global.CALL_AUTO_RETRY, 0); 244 mButtonAutoRetry.setChecked(autoretry != 0); 245 } else { 246 prefSet.removePreference(mButtonAutoRetry); 247 mButtonAutoRetry = null; 248 } 249 250 Preference cdmaOptions = prefSet.findPreference(BUTTON_CDMA_OPTIONS); 251 Preference gsmOptions = prefSet.findPreference(BUTTON_GSM_UMTS_OPTIONS); 252 if (carrierConfig.getBoolean(CarrierConfigManager.KEY_WORLD_PHONE_BOOL)) { 253 cdmaOptions.setIntent(mSubscriptionInfoHelper.getIntent(CdmaCallOptions.class)); 254 gsmOptions.setIntent(mSubscriptionInfoHelper.getIntent(GsmUmtsCallOptions.class)); 255 } else { 256 prefSet.removePreference(cdmaOptions); 257 prefSet.removePreference(gsmOptions); 258 259 int phoneType = mPhone.getPhoneType(); 260 Preference fdnButton = prefSet.findPreference(BUTTON_FDN_KEY); 261 if (carrierConfig.getBoolean(CarrierConfigManager.KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL)) { 262 prefSet.removePreference(fdnButton); 263 } else { 264 if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) { 265 prefSet.removePreference(fdnButton); 266 267 if (!carrierConfig.getBoolean( 268 CarrierConfigManager.KEY_VOICE_PRIVACY_DISABLE_UI_BOOL)) { 269 addPreferencesFromResource(R.xml.cdma_call_privacy); 270 } 271 } else if (phoneType == PhoneConstants.PHONE_TYPE_GSM) { 272 fdnButton.setIntent(mSubscriptionInfoHelper.getIntent(FdnSetting.class)); 273 274 if (carrierConfig.getBoolean( 275 CarrierConfigManager.KEY_ADDITIONAL_CALL_SETTING_BOOL)) { 276 addPreferencesFromResource(R.xml.gsm_umts_call_options); 277 GsmUmtsCallOptions.init(prefSet, mSubscriptionInfoHelper); 278 } 279 } else { 280 throw new IllegalStateException("Unexpected phone type: " + phoneType); 281 } 282 } 283 } 284 285 if (ImsManager.isVtEnabledByPlatform(mPhone.getContext()) && 286 ImsManager.isVtProvisionedOnDevice(mPhone.getContext()) && 287 mPhone.mDcTracker.isDataEnabled(true)) { 288 boolean currentValue = 289 ImsManager.isEnhanced4gLteModeSettingEnabledByUser(mPhone.getContext()) 290 ? PhoneGlobals.getInstance().phoneMgr.isVideoCallingEnabled( 291 getOpPackageName()) : false; 292 mEnableVideoCalling.setChecked(currentValue); 293 mEnableVideoCalling.setOnPreferenceChangeListener(this); 294 } else { 295 prefSet.removePreference(mEnableVideoCalling); 296 } 297 298 if (ImsManager.isVolteEnabledByPlatform(this) && 299 !carrierConfig.getBoolean( 300 CarrierConfigManager.KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL)) { 301 TelephonyManager tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE); 302 /* tm.listen(mPhoneStateListener, PhoneStateListener.LISTEN_CALL_STATE); */ 303 } 304 305 Preference wifiCallingSettings = findPreference( 306 getResources().getString(R.string.wifi_calling_settings_key)); 307 308 final PhoneAccountHandle simCallManager = mTelecomManager.getSimCallManager(); 309 if (simCallManager != null) { 310 Intent intent = PhoneAccountSettingsFragment.buildPhoneAccountConfigureIntent( 311 this, simCallManager); 312 if (intent != null) { 313 PackageManager pm = mPhone.getContext().getPackageManager(); 314 List<ResolveInfo> resolutions = pm.queryIntentActivities(intent, 0); 315 if (!resolutions.isEmpty()) { 316 wifiCallingSettings.setTitle(resolutions.get(0).loadLabel(pm)); 317 wifiCallingSettings.setSummary(null); 318 wifiCallingSettings.setIntent(intent); 319 } else { 320 prefSet.removePreference(wifiCallingSettings); 321 } 322 } else { 323 prefSet.removePreference(wifiCallingSettings); 324 } 325 } else if (!ImsManager.isWfcEnabledByPlatform(mPhone.getContext()) || 326 !ImsManager.isWfcProvisionedOnDevice(mPhone.getContext())) { 327 prefSet.removePreference(wifiCallingSettings); 328 } else { 329 int resId = com.android.internal.R.string.wifi_calling_off_summary; 330 if (ImsManager.isWfcEnabledByUser(mPhone.getContext())) { 331 int wfcMode = ImsManager.getWfcMode(mPhone.getContext()); 332 switch (wfcMode) { 333 case ImsConfig.WfcModeFeatureValueConstants.WIFI_ONLY: 334 resId = com.android.internal.R.string.wfc_mode_wifi_only_summary; 335 break; 336 case ImsConfig.WfcModeFeatureValueConstants.CELLULAR_PREFERRED: 337 resId = com.android.internal.R.string.wfc_mode_cellular_preferred_summary; 338 break; 339 case ImsConfig.WfcModeFeatureValueConstants.WIFI_PREFERRED: 340 resId = com.android.internal.R.string.wfc_mode_wifi_preferred_summary; 341 break; 342 default: 343 if (DBG) log("Unexpected WFC mode value: " + wfcMode); 344 } 345 } 346 wifiCallingSettings.setSummary(resId); 347 } 348 } 349 350 @Override 351 protected void onNewIntent(Intent newIntent) { 352 setIntent(newIntent); 353 354 mSubscriptionInfoHelper = new SubscriptionInfoHelper(this, getIntent()); 355 mSubscriptionInfoHelper.setActionBarTitle( 356 getActionBar(), getResources(), R.string.call_settings_with_label); 357 mPhone = mSubscriptionInfoHelper.getPhone(); 358 } 359 360 private static void log(String msg) { 361 Log.d(LOG_TAG, msg); 362 } 363 364 @Override 365 public boolean onOptionsItemSelected(MenuItem item) { 366 final int itemId = item.getItemId(); 367 if (itemId == android.R.id.home) { // See ActionBar#setDisplayHomeAsUpEnabled() 368 onBackPressed(); 369 return true; 370 } 371 return super.onOptionsItemSelected(item); 372 } 373 374 /** 375 * Finish current Activity and go up to the top level Settings ({@link CallFeaturesSetting}). 376 * This is useful for implementing "HomeAsUp" capability for second-level Settings. 377 */ 378 public static void goUpToTopLevelSetting( 379 Activity activity, SubscriptionInfoHelper subscriptionInfoHelper) { 380 Intent intent = subscriptionInfoHelper.getIntent(CallFeaturesSetting.class); 381 intent.setAction(Intent.ACTION_MAIN); 382 intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 383 activity.startActivity(intent); 384 activity.finish(); 385 } 386} 387