WirelessSettings.java revision a2904f9d5091ef5055d97adf72d32e8c19551c8e
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
17package com.android.settings;
18
19
20import android.app.Activity;
21import android.app.AlertDialog;
22import android.app.Dialog;
23import android.app.admin.DevicePolicyManager;
24import android.content.Context;
25import android.content.DialogInterface;
26import android.content.Intent;
27import android.content.pm.PackageManager;
28import android.content.res.Resources;
29import android.net.ConnectivityManager;
30import android.net.NetworkInfo;
31import android.nfc.NfcAdapter;
32import android.os.Bundle;
33import android.os.SystemProperties;
34import android.os.UserHandle;
35import android.preference.CheckBoxPreference;
36import android.preference.Preference;
37import android.preference.PreferenceScreen;
38import android.provider.Settings;
39import android.telephony.TelephonyManager;
40import android.text.TextUtils;
41import android.util.Log;
42import com.android.internal.telephony.TelephonyIntents;
43import com.android.internal.telephony.TelephonyProperties;
44import com.android.settings.nfc.NfcEnabler;
45import com.android.settings.NsdEnabler;
46
47public class WirelessSettings extends RestrictedSettingsFragment {
48    private static final String TAG = "WirelessSettings";
49
50    private static final String KEY_TOGGLE_AIRPLANE = "toggle_airplane";
51    private static final String KEY_TOGGLE_NFC = "toggle_nfc";
52    private static final String KEY_WIMAX_SETTINGS = "wimax_settings";
53    private static final String KEY_ANDROID_BEAM_SETTINGS = "android_beam_settings";
54    private static final String KEY_VPN_SETTINGS = "vpn_settings";
55    private static final String KEY_TETHER_SETTINGS = "tether_settings";
56    private static final String KEY_PROXY_SETTINGS = "proxy_settings";
57    private static final String KEY_MOBILE_NETWORK_SETTINGS = "mobile_network_settings";
58    private static final String KEY_MANAGE_MOBILE_PLAN = "manage_mobile_plan";
59    private static final String KEY_TOGGLE_NSD = "toggle_nsd"; //network service discovery
60    private static final String KEY_CELL_BROADCAST_SETTINGS = "cell_broadcast_settings";
61
62    public static final String EXIT_ECM_RESULT = "exit_ecm_result";
63    public static final int REQUEST_CODE_EXIT_ECM = 1;
64
65    private AirplaneModeEnabler mAirplaneModeEnabler;
66    private CheckBoxPreference mAirplaneModePreference;
67    private NfcEnabler mNfcEnabler;
68    private NfcAdapter mNfcAdapter;
69    private NsdEnabler mNsdEnabler;
70
71    private ConnectivityManager mCm;
72    private TelephonyManager mTm;
73
74    private static final int MANAGE_MOBILE_PLAN_DIALOG_ID = 1;
75    private static final String SAVED_MANAGE_MOBILE_PLAN_MSG = "mManageMobilePlanMessage";
76
77    public WirelessSettings() {
78        super(null);
79    }
80    /**
81     * Invoked on each preference click in this hierarchy, overrides
82     * PreferenceActivity's implementation.  Used to make sure we track the
83     * preference click events.
84     */
85    @Override
86    public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
87        if (ensurePinRestrictedPreference(preference)) {
88            return true;
89        }
90        log("onPreferenceTreeClick: preference=" + preference);
91        if (preference == mAirplaneModePreference && Boolean.parseBoolean(
92                SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE))) {
93            // In ECM mode launch ECM app dialog
94            startActivityForResult(
95                new Intent(TelephonyIntents.ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS, null),
96                REQUEST_CODE_EXIT_ECM);
97            return true;
98        } else if (preference == findPreference(KEY_MANAGE_MOBILE_PLAN)) {
99            onManageMobilePlanClick();
100        }
101        // Let the intents be launched by the Preference manager
102        return super.onPreferenceTreeClick(preferenceScreen, preference);
103    }
104
105    private String mManageMobilePlanMessage;
106    private static final String CONNECTED_TO_PROVISIONING_NETWORK_ACTION
107            = "com.android.server.connectivityservice.CONNECTED_TO_PROVISIONING_NETWORK_ACTION";
108    public void onManageMobilePlanClick() {
109        log("onManageMobilePlanClick:");
110        mManageMobilePlanMessage = null;
111        Resources resources = getActivity().getResources();
112
113        NetworkInfo ni = mCm.getProvisioningOrActiveNetworkInfo();
114        if (mTm.hasIccCard() && (ni != null)) {
115            // Get provisioning URL
116            String url = mCm.getMobileProvisioningUrl();
117            if (!TextUtils.isEmpty(url)) {
118                Intent intent = new Intent(CONNECTED_TO_PROVISIONING_NETWORK_ACTION);
119                intent.putExtra("EXTRA_URL", url);
120                Context context = getActivity().getBaseContext();
121                context.sendBroadcast(intent);
122                mManageMobilePlanMessage = null;
123            } else {
124                // No provisioning URL
125                String operatorName = mTm.getSimOperatorName();
126                if (TextUtils.isEmpty(operatorName)) {
127                    // Use NetworkOperatorName as second choice in case there is no
128                    // SPN (Service Provider Name on the SIM). Such as with T-mobile.
129                    operatorName = mTm.getNetworkOperatorName();
130                    if (TextUtils.isEmpty(operatorName)) {
131                        mManageMobilePlanMessage = resources.getString(
132                                R.string.mobile_unknown_sim_operator);
133                    } else {
134                        mManageMobilePlanMessage = resources.getString(
135                                R.string.mobile_no_provisioning_url, operatorName);
136                    }
137                } else {
138                    mManageMobilePlanMessage = resources.getString(
139                            R.string.mobile_no_provisioning_url, operatorName);
140                }
141            }
142        } else if (mTm.hasIccCard() == false) {
143            // No sim card
144            mManageMobilePlanMessage = resources.getString(R.string.mobile_insert_sim_card);
145        } else {
146            // NetworkInfo is null, there is no connection
147            mManageMobilePlanMessage = resources.getString(R.string.mobile_connect_to_internet);
148        }
149        if (!TextUtils.isEmpty(mManageMobilePlanMessage)) {
150            log("onManageMobilePlanClick: message=" + mManageMobilePlanMessage);
151            showDialog(MANAGE_MOBILE_PLAN_DIALOG_ID);
152        }
153    }
154
155    @Override
156    public Dialog onCreateDialog(int dialogId) {
157        log("onCreateDialog: dialogId=" + dialogId);
158        switch (dialogId) {
159            case MANAGE_MOBILE_PLAN_DIALOG_ID:
160                return new AlertDialog.Builder(getActivity())
161                            .setMessage(mManageMobilePlanMessage)
162                            .setCancelable(false)
163                            .setPositiveButton(com.android.internal.R.string.ok,
164                                    new DialogInterface.OnClickListener() {
165                                @Override
166                                public void onClick(DialogInterface dialog, int id) {
167                                    log("MANAGE_MOBILE_PLAN_DIALOG.onClickListener id=" + id);
168                                    mManageMobilePlanMessage = null;
169                                }
170                            })
171                            .create();
172        }
173        return super.onCreateDialog(dialogId);
174    }
175
176    private void log(String s) {
177        Log.d(TAG, s);
178    }
179
180    public static boolean isRadioAllowed(Context context, String type) {
181        if (!AirplaneModeEnabler.isAirplaneModeOn(context)) {
182            return true;
183        }
184        // Here we use the same logic in onCreate().
185        String toggleable = Settings.Global.getString(context.getContentResolver(),
186                Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS);
187        return toggleable != null && toggleable.contains(type);
188    }
189
190    @Override
191    public void onCreate(Bundle savedInstanceState) {
192        super.onCreate(savedInstanceState);
193        if (savedInstanceState != null) {
194            mManageMobilePlanMessage = savedInstanceState.getString(SAVED_MANAGE_MOBILE_PLAN_MSG);
195        }
196        log("onCreate: mManageMobilePlanMessage=" + mManageMobilePlanMessage);
197
198        mCm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
199        mTm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
200
201        addPreferencesFromResource(R.xml.wireless_settings);
202
203        final boolean isSecondaryUser = UserHandle.myUserId() != UserHandle.USER_OWNER;
204
205        final Activity activity = getActivity();
206        mAirplaneModePreference = (CheckBoxPreference) findPreference(KEY_TOGGLE_AIRPLANE);
207        CheckBoxPreference nfc = (CheckBoxPreference) findPreference(KEY_TOGGLE_NFC);
208        PreferenceScreen androidBeam = (PreferenceScreen) findPreference(KEY_ANDROID_BEAM_SETTINGS);
209        CheckBoxPreference nsd = (CheckBoxPreference) findPreference(KEY_TOGGLE_NSD);
210
211        mAirplaneModeEnabler = new AirplaneModeEnabler(activity, mAirplaneModePreference);
212        mNfcEnabler = new NfcEnabler(activity, nfc, androidBeam);
213
214        // Remove NSD checkbox by default
215        getPreferenceScreen().removePreference(nsd);
216        //mNsdEnabler = new NsdEnabler(activity, nsd);
217
218        String toggleable = Settings.Global.getString(activity.getContentResolver(),
219                Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS);
220
221        //enable/disable wimax depending on the value in config.xml
222        boolean isWimaxEnabled = !isSecondaryUser && this.getResources().getBoolean(
223                com.android.internal.R.bool.config_wimaxEnabled);
224        if (!isWimaxEnabled) {
225            PreferenceScreen root = getPreferenceScreen();
226            Preference ps = (Preference) findPreference(KEY_WIMAX_SETTINGS);
227            if (ps != null) root.removePreference(ps);
228        } else {
229            if (toggleable == null || !toggleable.contains(Settings.Global.RADIO_WIMAX )
230                    && isWimaxEnabled) {
231                Preference ps = (Preference) findPreference(KEY_WIMAX_SETTINGS);
232                ps.setDependency(KEY_TOGGLE_AIRPLANE);
233            }
234        }
235        protectByRestrictions(KEY_WIMAX_SETTINGS);
236
237        // Manually set dependencies for Wifi when not toggleable.
238        if (toggleable == null || !toggleable.contains(Settings.Global.RADIO_WIFI)) {
239            findPreference(KEY_VPN_SETTINGS).setDependency(KEY_TOGGLE_AIRPLANE);
240        }
241        if (isSecondaryUser) { // Disable VPN
242            removePreference(KEY_VPN_SETTINGS);
243        }
244        protectByRestrictions(KEY_VPN_SETTINGS);
245        // Manually set dependencies for Bluetooth when not toggleable.
246        if (toggleable == null || !toggleable.contains(Settings.Global.RADIO_BLUETOOTH)) {
247            // No bluetooth-dependent items in the list. Code kept in case one is added later.
248        }
249
250        // Manually set dependencies for NFC when not toggleable.
251        if (toggleable == null || !toggleable.contains(Settings.Global.RADIO_NFC)) {
252            findPreference(KEY_TOGGLE_NFC).setDependency(KEY_TOGGLE_AIRPLANE);
253            findPreference(KEY_ANDROID_BEAM_SETTINGS).setDependency(KEY_TOGGLE_AIRPLANE);
254        }
255
256        // Remove NFC if its not available
257        mNfcAdapter = NfcAdapter.getDefaultAdapter(activity);
258        if (mNfcAdapter == null) {
259            getPreferenceScreen().removePreference(nfc);
260            getPreferenceScreen().removePreference(androidBeam);
261            mNfcEnabler = null;
262        }
263
264        // Remove Mobile Network Settings and Manage Mobile Plan if it's a wifi-only device.
265        if (isSecondaryUser || Utils.isWifiOnly(getActivity())) {
266            removePreference(KEY_MOBILE_NETWORK_SETTINGS);
267            removePreference(KEY_MANAGE_MOBILE_PLAN);
268        }
269        protectByRestrictions(KEY_MOBILE_NETWORK_SETTINGS);
270        protectByRestrictions(KEY_MANAGE_MOBILE_PLAN);
271
272        // Remove Airplane Mode settings if it's a stationary device such as a TV.
273        if (getActivity().getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEVISION)) {
274            removePreference(KEY_TOGGLE_AIRPLANE);
275        }
276
277        // Enable Proxy selector settings if allowed.
278        Preference mGlobalProxy = findPreference(KEY_PROXY_SETTINGS);
279        DevicePolicyManager mDPM = (DevicePolicyManager)
280                activity.getSystemService(Context.DEVICE_POLICY_SERVICE);
281        // proxy UI disabled until we have better app support
282        getPreferenceScreen().removePreference(mGlobalProxy);
283        mGlobalProxy.setEnabled(mDPM.getGlobalProxyAdmin() == null);
284
285        // Disable Tethering if it's not allowed or if it's a wifi-only device
286        ConnectivityManager cm =
287                (ConnectivityManager) activity.getSystemService(Context.CONNECTIVITY_SERVICE);
288        if (isSecondaryUser || !cm.isTetheringSupported()) {
289            getPreferenceScreen().removePreference(findPreference(KEY_TETHER_SETTINGS));
290        } else {
291            Preference p = findPreference(KEY_TETHER_SETTINGS);
292            p.setTitle(Utils.getTetheringLabel(cm));
293        }
294        protectByRestrictions(KEY_TETHER_SETTINGS);
295
296        // Enable link to CMAS app settings depending on the value in config.xml.
297        boolean isCellBroadcastAppLinkEnabled = this.getResources().getBoolean(
298                com.android.internal.R.bool.config_cellBroadcastAppLinks);
299        try {
300            if (isCellBroadcastAppLinkEnabled) {
301                PackageManager pm = getPackageManager();
302                if (pm.getApplicationEnabledSetting("com.android.cellbroadcastreceiver")
303                        == PackageManager.COMPONENT_ENABLED_STATE_DISABLED) {
304                    isCellBroadcastAppLinkEnabled = false;  // CMAS app disabled
305                }
306            }
307        } catch (IllegalArgumentException ignored) {
308            isCellBroadcastAppLinkEnabled = false;  // CMAS app not installed
309        }
310        if (isSecondaryUser || !isCellBroadcastAppLinkEnabled) {
311            PreferenceScreen root = getPreferenceScreen();
312            Preference ps = findPreference(KEY_CELL_BROADCAST_SETTINGS);
313            if (ps != null) root.removePreference(ps);
314        }
315        protectByRestrictions(KEY_CELL_BROADCAST_SETTINGS);
316    }
317
318    @Override
319    public void onResume() {
320        super.onResume();
321
322        mAirplaneModeEnabler.resume();
323        if (mNfcEnabler != null) {
324            mNfcEnabler.resume();
325        }
326        if (mNsdEnabler != null) {
327            mNsdEnabler.resume();
328        }
329    }
330
331    @Override
332    public void onSaveInstanceState(Bundle outState) {
333        super.onSaveInstanceState(outState);
334
335        if (!TextUtils.isEmpty(mManageMobilePlanMessage)) {
336            outState.putString(SAVED_MANAGE_MOBILE_PLAN_MSG, mManageMobilePlanMessage);
337        }
338    }
339
340    @Override
341    public void onPause() {
342        super.onPause();
343
344        mAirplaneModeEnabler.pause();
345        if (mNfcEnabler != null) {
346            mNfcEnabler.pause();
347        }
348        if (mNsdEnabler != null) {
349            mNsdEnabler.pause();
350        }
351    }
352
353    @Override
354    public void onActivityResult(int requestCode, int resultCode, Intent data) {
355        if (requestCode == REQUEST_CODE_EXIT_ECM) {
356            Boolean isChoiceYes = data.getBooleanExtra(EXIT_ECM_RESULT, false);
357            // Set Airplane mode based on the return value and checkbox state
358            mAirplaneModeEnabler.setAirplaneModeInECM(isChoiceYes,
359                    mAirplaneModePreference.isChecked());
360        }
361        super.onActivityResult(requestCode, resultCode, data);
362    }
363
364    @Override
365    protected int getHelpResource() {
366        return R.string.help_url_more_networks;
367    }
368}
369