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