• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2009 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.settings;
18 
19 
20 import android.app.Activity;
21 import android.app.AlertDialog;
22 import android.app.Dialog;
23 import android.app.admin.DevicePolicyManager;
24 import android.content.ActivityNotFoundException;
25 import android.content.Context;
26 import android.content.DialogInterface;
27 import android.content.Intent;
28 import android.content.pm.PackageManager;
29 import android.content.res.Resources;
30 import android.net.ConnectivityManager;
31 import android.net.NetworkInfo;
32 import android.net.Uri;
33 import android.nfc.NfcAdapter;
34 import android.nfc.NfcManager;
35 import android.os.Bundle;
36 import android.os.SystemProperties;
37 import android.os.UserHandle;
38 import android.os.UserManager;
39 import android.provider.SearchIndexableResource;
40 import android.provider.Settings;
41 import android.support.v14.preference.SwitchPreference;
42 import android.support.v7.preference.Preference;
43 import android.support.v7.preference.PreferenceScreen;
44 import android.telephony.TelephonyManager;
45 import android.text.TextUtils;
46 import android.util.Log;
47 
48 import com.android.ims.ImsManager;
49 import com.android.internal.logging.MetricsProto.MetricsEvent;
50 import com.android.internal.telephony.TelephonyIntents;
51 import com.android.internal.telephony.TelephonyProperties;
52 import com.android.settings.nfc.NfcEnabler;
53 import com.android.settings.search.BaseSearchIndexProvider;
54 import com.android.settings.search.Indexable;
55 import com.android.settingslib.RestrictedLockUtils;
56 import com.android.settingslib.RestrictedPreference;
57 
58 import java.util.ArrayList;
59 import java.util.Arrays;
60 import java.util.List;
61 
62 public class WirelessSettings extends SettingsPreferenceFragment implements Indexable {
63     private static final String TAG = "WirelessSettings";
64 
65     private static final String KEY_TOGGLE_AIRPLANE = "toggle_airplane";
66     private static final String KEY_TOGGLE_NFC = "toggle_nfc";
67     private static final String KEY_WIMAX_SETTINGS = "wimax_settings";
68     private static final String KEY_ANDROID_BEAM_SETTINGS = "android_beam_settings";
69     private static final String KEY_VPN_SETTINGS = "vpn_settings";
70     private static final String KEY_TETHER_SETTINGS = "tether_settings";
71     private static final String KEY_PROXY_SETTINGS = "proxy_settings";
72     private static final String KEY_MOBILE_NETWORK_SETTINGS = "mobile_network_settings";
73     private static final String KEY_MANAGE_MOBILE_PLAN = "manage_mobile_plan";
74     private static final String KEY_WFC_SETTINGS = "wifi_calling_settings";
75 
76     public static final String EXIT_ECM_RESULT = "exit_ecm_result";
77     public static final int REQUEST_CODE_EXIT_ECM = 1;
78 
79     private AirplaneModeEnabler mAirplaneModeEnabler;
80     private SwitchPreference mAirplaneModePreference;
81     private NfcEnabler mNfcEnabler;
82     private NfcAdapter mNfcAdapter;
83 
84     private ConnectivityManager mCm;
85     private TelephonyManager mTm;
86     private PackageManager mPm;
87     private UserManager mUm;
88 
89     private static final int MANAGE_MOBILE_PLAN_DIALOG_ID = 1;
90     private static final String SAVED_MANAGE_MOBILE_PLAN_MSG = "mManageMobilePlanMessage";
91 
92     private PreferenceScreen mButtonWfc;
93 
94     /**
95      * Invoked on each preference click in this hierarchy, overrides
96      * PreferenceFragment's implementation.  Used to make sure we track the
97      * preference click events.
98      */
99     @Override
onPreferenceTreeClick(Preference preference)100     public boolean onPreferenceTreeClick(Preference preference) {
101         log("onPreferenceTreeClick: preference=" + preference);
102         if (preference == mAirplaneModePreference && Boolean.parseBoolean(
103                 SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE))) {
104             // In ECM mode launch ECM app dialog
105             startActivityForResult(
106                 new Intent(TelephonyIntents.ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS, null),
107                 REQUEST_CODE_EXIT_ECM);
108             return true;
109         } else if (preference == findPreference(KEY_MANAGE_MOBILE_PLAN)) {
110             onManageMobilePlanClick();
111         }
112         // Let the intents be launched by the Preference manager
113         return super.onPreferenceTreeClick(preference);
114     }
115 
116     private String mManageMobilePlanMessage;
onManageMobilePlanClick()117     public void onManageMobilePlanClick() {
118         log("onManageMobilePlanClick:");
119         mManageMobilePlanMessage = null;
120         Resources resources = getActivity().getResources();
121 
122         NetworkInfo ni = mCm.getActiveNetworkInfo();
123         if (mTm.hasIccCard() && (ni != null)) {
124             // Check for carrier apps that can handle provisioning first
125             Intent provisioningIntent = new Intent(TelephonyIntents.ACTION_CARRIER_SETUP);
126             List<String> carrierPackages =
127                     mTm.getCarrierPackageNamesForIntent(provisioningIntent);
128             if (carrierPackages != null && !carrierPackages.isEmpty()) {
129                 if (carrierPackages.size() != 1) {
130                     Log.w(TAG, "Multiple matching carrier apps found, launching the first.");
131                 }
132                 provisioningIntent.setPackage(carrierPackages.get(0));
133                 startActivity(provisioningIntent);
134                 return;
135             }
136 
137             // Get provisioning URL
138             String url = mCm.getMobileProvisioningUrl();
139             if (!TextUtils.isEmpty(url)) {
140                 Intent intent = Intent.makeMainSelectorActivity(Intent.ACTION_MAIN,
141                         Intent.CATEGORY_APP_BROWSER);
142                 intent.setData(Uri.parse(url));
143                 intent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT |
144                         Intent.FLAG_ACTIVITY_NEW_TASK);
145                 try {
146                     startActivity(intent);
147                 } catch (ActivityNotFoundException e) {
148                     Log.w(TAG, "onManageMobilePlanClick: startActivity failed" + e);
149                 }
150             } else {
151                 // No provisioning URL
152                 String operatorName = mTm.getSimOperatorName();
153                 if (TextUtils.isEmpty(operatorName)) {
154                     // Use NetworkOperatorName as second choice in case there is no
155                     // SPN (Service Provider Name on the SIM). Such as with T-mobile.
156                     operatorName = mTm.getNetworkOperatorName();
157                     if (TextUtils.isEmpty(operatorName)) {
158                         mManageMobilePlanMessage = resources.getString(
159                                 R.string.mobile_unknown_sim_operator);
160                     } else {
161                         mManageMobilePlanMessage = resources.getString(
162                                 R.string.mobile_no_provisioning_url, operatorName);
163                     }
164                 } else {
165                     mManageMobilePlanMessage = resources.getString(
166                             R.string.mobile_no_provisioning_url, operatorName);
167                 }
168             }
169         } else if (mTm.hasIccCard() == false) {
170             // No sim card
171             mManageMobilePlanMessage = resources.getString(R.string.mobile_insert_sim_card);
172         } else {
173             // NetworkInfo is null, there is no connection
174             mManageMobilePlanMessage = resources.getString(R.string.mobile_connect_to_internet);
175         }
176         if (!TextUtils.isEmpty(mManageMobilePlanMessage)) {
177             log("onManageMobilePlanClick: message=" + mManageMobilePlanMessage);
178             showDialog(MANAGE_MOBILE_PLAN_DIALOG_ID);
179         }
180     }
181 
182     @Override
onCreateDialog(int dialogId)183     public Dialog onCreateDialog(int dialogId) {
184         log("onCreateDialog: dialogId=" + dialogId);
185         switch (dialogId) {
186             case MANAGE_MOBILE_PLAN_DIALOG_ID:
187                 return new AlertDialog.Builder(getActivity())
188                             .setMessage(mManageMobilePlanMessage)
189                             .setCancelable(false)
190                             .setPositiveButton(com.android.internal.R.string.ok,
191                                     new DialogInterface.OnClickListener() {
192                                 @Override
193                                 public void onClick(DialogInterface dialog, int id) {
194                                     log("MANAGE_MOBILE_PLAN_DIALOG.onClickListener id=" + id);
195                                     mManageMobilePlanMessage = null;
196                                 }
197                             })
198                             .create();
199         }
200         return super.onCreateDialog(dialogId);
201     }
202 
203     private void log(String s) {
204         Log.d(TAG, s);
205     }
206 
207     @Override
208     protected int getMetricsCategory() {
209         return MetricsEvent.WIRELESS;
210     }
211 
212     @Override
213     public void onCreate(Bundle savedInstanceState) {
214         super.onCreate(savedInstanceState);
215         if (savedInstanceState != null) {
216             mManageMobilePlanMessage = savedInstanceState.getString(SAVED_MANAGE_MOBILE_PLAN_MSG);
217         }
218         log("onCreate: mManageMobilePlanMessage=" + mManageMobilePlanMessage);
219 
220         mCm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
221         mTm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
222         mPm = getPackageManager();
223         mUm = (UserManager) getSystemService(Context.USER_SERVICE);
224 
225         addPreferencesFromResource(R.xml.wireless_settings);
226 
227         final boolean isAdmin = mUm.isAdminUser();
228 
229         final Activity activity = getActivity();
230         mAirplaneModePreference = (SwitchPreference) findPreference(KEY_TOGGLE_AIRPLANE);
231         SwitchPreference nfc = (SwitchPreference) findPreference(KEY_TOGGLE_NFC);
232         RestrictedPreference androidBeam = (RestrictedPreference) findPreference(
233                 KEY_ANDROID_BEAM_SETTINGS);
234 
235         mAirplaneModeEnabler = new AirplaneModeEnabler(activity, mAirplaneModePreference);
236         mNfcEnabler = new NfcEnabler(activity, nfc, androidBeam);
237 
238         mButtonWfc = (PreferenceScreen) findPreference(KEY_WFC_SETTINGS);
239 
240         String toggleable = Settings.Global.getString(activity.getContentResolver(),
241                 Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS);
242 
243         //enable/disable wimax depending on the value in config.xml
244         final boolean isWimaxEnabled = isAdmin && this.getResources().getBoolean(
245                 com.android.internal.R.bool.config_wimaxEnabled);
246         if (!isWimaxEnabled || RestrictedLockUtils.hasBaseUserRestriction(activity,
247                 UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS, UserHandle.myUserId())) {
248             PreferenceScreen root = getPreferenceScreen();
249             Preference ps = findPreference(KEY_WIMAX_SETTINGS);
250             if (ps != null) root.removePreference(ps);
251         } else {
252             if (toggleable == null || !toggleable.contains(Settings.Global.RADIO_WIMAX )
253                     && isWimaxEnabled) {
254                 Preference ps = findPreference(KEY_WIMAX_SETTINGS);
255                 ps.setDependency(KEY_TOGGLE_AIRPLANE);
256             }
257         }
258 
259         // Manually set dependencies for Wifi when not toggleable.
260         if (toggleable == null || !toggleable.contains(Settings.Global.RADIO_WIFI)) {
261             findPreference(KEY_VPN_SETTINGS).setDependency(KEY_TOGGLE_AIRPLANE);
262         }
263         // Disable VPN.
264         // TODO: http://b/23693383
265         if (!isAdmin || RestrictedLockUtils.hasBaseUserRestriction(activity,
266                 UserManager.DISALLOW_CONFIG_VPN, UserHandle.myUserId())) {
267             removePreference(KEY_VPN_SETTINGS);
268         }
269 
270         // Manually set dependencies for Bluetooth when not toggleable.
271         if (toggleable == null || !toggleable.contains(Settings.Global.RADIO_BLUETOOTH)) {
272             // No bluetooth-dependent items in the list. Code kept in case one is added later.
273         }
274 
275         // Manually set dependencies for NFC when not toggleable.
276         if (toggleable == null || !toggleable.contains(Settings.Global.RADIO_NFC)) {
277             findPreference(KEY_TOGGLE_NFC).setDependency(KEY_TOGGLE_AIRPLANE);
278             findPreference(KEY_ANDROID_BEAM_SETTINGS).setDependency(KEY_TOGGLE_AIRPLANE);
279         }
280 
281         // Remove NFC if not available
282         mNfcAdapter = NfcAdapter.getDefaultAdapter(activity);
283         if (mNfcAdapter == null) {
284             getPreferenceScreen().removePreference(nfc);
285             getPreferenceScreen().removePreference(androidBeam);
286             mNfcEnabler = null;
287         }
288 
289         // Remove Mobile Network Settings and Manage Mobile Plan for secondary users,
290         // if it's a wifi-only device.
291         if (!isAdmin || Utils.isWifiOnly(getActivity()) ||
292                 RestrictedLockUtils.hasBaseUserRestriction(activity,
293                         UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS, UserHandle.myUserId())) {
294             removePreference(KEY_MOBILE_NETWORK_SETTINGS);
295             removePreference(KEY_MANAGE_MOBILE_PLAN);
296         }
297         // Remove Mobile Network Settings and Manage Mobile Plan
298         // if config_show_mobile_plan sets false.
299         final boolean isMobilePlanEnabled = this.getResources().getBoolean(
300                 R.bool.config_show_mobile_plan);
301         if (!isMobilePlanEnabled) {
302             Preference pref = findPreference(KEY_MANAGE_MOBILE_PLAN);
303             if (pref != null) {
304                 removePreference(KEY_MANAGE_MOBILE_PLAN);
305             }
306         }
307 
308         // Remove Airplane Mode settings if it's a stationary device such as a TV.
309         if (mPm.hasSystemFeature(PackageManager.FEATURE_TELEVISION)) {
310             removePreference(KEY_TOGGLE_AIRPLANE);
311         }
312 
313         // Enable Proxy selector settings if allowed.
314         Preference mGlobalProxy = findPreference(KEY_PROXY_SETTINGS);
315         final DevicePolicyManager mDPM = (DevicePolicyManager)
316                 activity.getSystemService(Context.DEVICE_POLICY_SERVICE);
317         // proxy UI disabled until we have better app support
318         getPreferenceScreen().removePreference(mGlobalProxy);
319         mGlobalProxy.setEnabled(mDPM.getGlobalProxyAdmin() == null);
320 
321         // Disable Tethering if it's not allowed or if it's a wifi-only device
322         final ConnectivityManager cm =
323                 (ConnectivityManager) activity.getSystemService(Context.CONNECTIVITY_SERVICE);
324 
325         final boolean adminDisallowedTetherConfig = RestrictedLockUtils.checkIfRestrictionEnforced(
326                 activity, UserManager.DISALLOW_CONFIG_TETHERING, UserHandle.myUserId()) != null;
327         if ((!cm.isTetheringSupported() && !adminDisallowedTetherConfig) ||
328                 RestrictedLockUtils.hasBaseUserRestriction(activity,
329                         UserManager.DISALLOW_CONFIG_TETHERING, UserHandle.myUserId())) {
330             getPreferenceScreen().removePreference(findPreference(KEY_TETHER_SETTINGS));
331         } else if (!adminDisallowedTetherConfig) {
332             Preference p = findPreference(KEY_TETHER_SETTINGS);
333             p.setTitle(com.android.settingslib.Utils.getTetheringLabel(cm));
334 
335             // Grey out if provisioning is not available.
336             p.setEnabled(!TetherSettings
337                     .isProvisioningNeededButUnavailable(getActivity()));
338         }
339     }
340 
341     @Override
342     public void onResume() {
343         super.onResume();
344 
345         mAirplaneModeEnabler.resume();
346         if (mNfcEnabler != null) {
347             mNfcEnabler.resume();
348         }
349 
350         // update WFC setting
351         final Context context = getActivity();
352         if (ImsManager.isWfcEnabledByPlatform(context)) {
353             getPreferenceScreen().addPreference(mButtonWfc);
354 
355             mButtonWfc.setSummary(WifiCallingSettings.getWfcModeSummary(
356                     context, ImsManager.getWfcMode(context)));
357         } else {
358             removePreference(KEY_WFC_SETTINGS);
359         }
360     }
361 
362     @Override
363     public void onSaveInstanceState(Bundle outState) {
364         super.onSaveInstanceState(outState);
365 
366         if (!TextUtils.isEmpty(mManageMobilePlanMessage)) {
367             outState.putString(SAVED_MANAGE_MOBILE_PLAN_MSG, mManageMobilePlanMessage);
368         }
369     }
370 
371     @Override
372     public void onPause() {
373         super.onPause();
374 
375         mAirplaneModeEnabler.pause();
376         if (mNfcEnabler != null) {
377             mNfcEnabler.pause();
378         }
379     }
380 
381     @Override
382     public void onActivityResult(int requestCode, int resultCode, Intent data) {
383         if (requestCode == REQUEST_CODE_EXIT_ECM) {
384             Boolean isChoiceYes = data.getBooleanExtra(EXIT_ECM_RESULT, false);
385             // Set Airplane mode based on the return value and checkbox state
386             mAirplaneModeEnabler.setAirplaneModeInECM(isChoiceYes,
387                     mAirplaneModePreference.isChecked());
388         }
389         super.onActivityResult(requestCode, resultCode, data);
390     }
391 
392     @Override
393     protected int getHelpResource() {
394         return R.string.help_url_more_networks;
395     }
396 
397     /**
398      * For Search.
399      */
400     public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
401         new BaseSearchIndexProvider() {
402             @Override
403             public List<SearchIndexableResource> getXmlResourcesToIndex(
404                     Context context, boolean enabled) {
405                 SearchIndexableResource sir = new SearchIndexableResource(context);
406                 sir.xmlResId = R.xml.wireless_settings;
407                 return Arrays.asList(sir);
408             }
409 
410             @Override
411             public List<String> getNonIndexableKeys(Context context) {
412                 final ArrayList<String> result = new ArrayList<String>();
413 
414                 final UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE);
415                 final boolean isSecondaryUser = !um.isAdminUser();
416                 final boolean isWimaxEnabled = !isSecondaryUser
417                         && context.getResources().getBoolean(
418                         com.android.internal.R.bool.config_wimaxEnabled);
419                 if (!isWimaxEnabled) {
420                     result.add(KEY_WIMAX_SETTINGS);
421                 }
422 
423                 if (isSecondaryUser) { // Disable VPN
424                     result.add(KEY_VPN_SETTINGS);
425                 }
426 
427                 // Remove NFC if not available
428                 final NfcManager manager = (NfcManager)
429                         context.getSystemService(Context.NFC_SERVICE);
430                 if (manager != null) {
431                     NfcAdapter adapter = manager.getDefaultAdapter();
432                     if (adapter == null) {
433                         result.add(KEY_TOGGLE_NFC);
434                         result.add(KEY_ANDROID_BEAM_SETTINGS);
435                     }
436                 }
437 
438                 // Remove Mobile Network Settings and Manage Mobile Plan if it's a wifi-only device.
439                 if (isSecondaryUser || Utils.isWifiOnly(context)) {
440                     result.add(KEY_MOBILE_NETWORK_SETTINGS);
441                     result.add(KEY_MANAGE_MOBILE_PLAN);
442                 }
443 
444                 // Remove Mobile Network Settings and Manage Mobile Plan
445                 // if config_show_mobile_plan sets false.
446                 final boolean isMobilePlanEnabled = context.getResources().getBoolean(
447                         R.bool.config_show_mobile_plan);
448                 if (!isMobilePlanEnabled) {
449                     result.add(KEY_MANAGE_MOBILE_PLAN);
450                 }
451 
452                 final PackageManager pm = context.getPackageManager();
453 
454                 // Remove Airplane Mode settings if it's a stationary device such as a TV.
455                 if (pm.hasSystemFeature(PackageManager.FEATURE_TELEVISION)) {
456                     result.add(KEY_TOGGLE_AIRPLANE);
457                 }
458 
459                 // proxy UI disabled until we have better app support
460                 result.add(KEY_PROXY_SETTINGS);
461 
462                 // Disable Tethering if it's not allowed or if it's a wifi-only device
463                 ConnectivityManager cm = (ConnectivityManager)
464                         context.getSystemService(Context.CONNECTIVITY_SERVICE);
465                 if (isSecondaryUser || !cm.isTetheringSupported()) {
466                     result.add(KEY_TETHER_SETTINGS);
467                 }
468 
469                 if (!ImsManager.isWfcEnabledByPlatform(context)) {
470                     result.add(KEY_WFC_SETTINGS);
471                 }
472 
473                 return result;
474             }
475         };
476 }
477