OSDN Git Service

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