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