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