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