• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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