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