1 /* 2 * Copyright (C) 2010 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.wifi; 18 19 import static android.net.wifi.WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_ENABLED; 20 import static android.os.UserManager.DISALLOW_CONFIG_WIFI; 21 22 import android.app.Activity; 23 import android.app.Dialog; 24 import android.app.settings.SettingsEnums; 25 import android.content.ActivityNotFoundException; 26 import android.content.ContentResolver; 27 import android.content.Context; 28 import android.content.DialogInterface; 29 import android.content.Intent; 30 import android.net.NetworkTemplate; 31 import android.net.wifi.WifiConfiguration; 32 import android.net.wifi.WifiManager; 33 import android.os.Bundle; 34 import android.os.Handler; 35 import android.os.HandlerThread; 36 import android.os.Looper; 37 import android.os.PowerManager; 38 import android.os.Process; 39 import android.os.SimpleClock; 40 import android.os.SystemClock; 41 import android.provider.Settings; 42 import android.text.TextUtils; 43 import android.util.FeatureFlagUtils; 44 import android.util.Log; 45 import android.view.ContextMenu; 46 import android.view.ContextMenu.ContextMenuInfo; 47 import android.view.Menu; 48 import android.view.MenuItem; 49 import android.view.View; 50 import android.widget.Toast; 51 52 import androidx.annotation.VisibleForTesting; 53 import androidx.preference.Preference; 54 import androidx.preference.PreferenceCategory; 55 import androidx.preference.PreferenceScreen; 56 import androidx.recyclerview.widget.RecyclerView; 57 58 import com.android.settings.LinkifyUtils; 59 import com.android.settings.R; 60 import com.android.settings.RestrictedSettingsFragment; 61 import com.android.settings.SettingsActivity; 62 import com.android.settings.Utils; 63 import com.android.settings.core.FeatureFlags; 64 import com.android.settings.core.SubSettingLauncher; 65 import com.android.settings.datausage.DataUsagePreference; 66 import com.android.settings.datausage.DataUsageUtils; 67 import com.android.settings.location.WifiScanningFragment; 68 import com.android.settings.overlay.FeatureFactory; 69 import com.android.settings.search.BaseSearchIndexProvider; 70 import com.android.settings.widget.MainSwitchBarController; 71 import com.android.settings.wifi.details.WifiNetworkDetailsFragment; 72 import com.android.settings.wifi.dpp.WifiDppUtils; 73 import com.android.settingslib.HelpUtils; 74 import com.android.settingslib.RestrictedLockUtils; 75 import com.android.settingslib.RestrictedLockUtilsInternal; 76 import com.android.settingslib.search.Indexable; 77 import com.android.settingslib.search.SearchIndexable; 78 import com.android.settingslib.wifi.LongPressWifiEntryPreference; 79 import com.android.settingslib.wifi.WifiSavedConfigUtils; 80 import com.android.wifitrackerlib.WifiEntry; 81 import com.android.wifitrackerlib.WifiEntry.ConnectCallback; 82 import com.android.wifitrackerlib.WifiPickerTracker; 83 84 import java.time.Clock; 85 import java.time.ZoneOffset; 86 import java.util.List; 87 import java.util.Optional; 88 89 /** 90 * UI for Wi-Fi settings screen 91 * 92 * @deprecated This file will be deprecated at Android S, please merge your WifiSettings 93 * in change in {@link NetworkProviderSettings}. 94 */ 95 @Deprecated 96 @SearchIndexable 97 public class WifiSettings extends RestrictedSettingsFragment 98 implements Indexable, WifiPickerTracker.WifiPickerTrackerCallback, 99 WifiDialog2.WifiDialog2Listener, DialogInterface.OnDismissListener { 100 101 private static final String TAG = "WifiSettings"; 102 103 // Set the Provider Model is always enabled 104 @VisibleForTesting 105 static Boolean IS_ENABLED_PROVIDER_MODEL = true; 106 107 // IDs of context menu 108 static final int MENU_ID_CONNECT = Menu.FIRST + 1; 109 @VisibleForTesting 110 static final int MENU_ID_DISCONNECT = Menu.FIRST + 2; 111 @VisibleForTesting 112 static final int MENU_ID_FORGET = Menu.FIRST + 3; 113 static final int MENU_ID_MODIFY = Menu.FIRST + 4; 114 static final int MENU_ID_SHARE = Menu.FIRST + 5; 115 116 // Max age of tracked WifiEntries 117 private static final long MAX_SCAN_AGE_MILLIS = 15_000; 118 // Interval between initiating WifiPickerTracker scans 119 private static final long SCAN_INTERVAL_MILLIS = 10_000; 120 121 @VisibleForTesting 122 static final int ADD_NETWORK_REQUEST = 2; 123 static final int CONFIG_NETWORK_REQUEST = 3; 124 static final int MANAGE_SUBSCRIPTION = 4; 125 126 private static final String PREF_KEY_EMPTY_WIFI_LIST = "wifi_empty_list"; 127 // TODO(b/70983952): Rename these to use WifiEntry instead of AccessPoint. 128 private static final String PREF_KEY_CONNECTED_ACCESS_POINTS = "connected_access_point"; 129 private static final String PREF_KEY_ACCESS_POINTS = "access_points"; 130 private static final String PREF_KEY_CONFIGURE_WIFI_SETTINGS = "configure_wifi_settings"; 131 private static final String PREF_KEY_SAVED_NETWORKS = "saved_networks"; 132 private static final String PREF_KEY_STATUS_MESSAGE = "wifi_status_message"; 133 @VisibleForTesting 134 static final String PREF_KEY_DATA_USAGE = "wifi_data_usage"; 135 136 private static final int REQUEST_CODE_WIFI_DPP_ENROLLEE_QR_CODE_SCANNER = 0; 137 138 public static final int WIFI_DIALOG_ID = 1; 139 140 // Instance state keys 141 private static final String SAVE_DIALOG_MODE = "dialog_mode"; 142 private static final String SAVE_DIALOG_WIFIENTRY_KEY = "wifi_ap_key"; 143 144 // Cache at onCreateContextMenu and use at onContextItemSelected. Don't use it in other methods. 145 private WifiEntry mSelectedWifiEntry; 146 147 // Save the dialog details 148 private int mDialogMode; 149 private String mDialogWifiEntryKey; 150 private WifiEntry mDialogWifiEntry; 151 152 // This boolean extra specifies whether to enable the Next button when connected. Used by 153 // account creation outside of setup wizard. 154 private static final String EXTRA_ENABLE_NEXT_ON_CONNECT = "wifi_enable_next_on_connect"; 155 156 // Enable the Next button when a Wi-Fi network is connected. 157 private boolean mEnableNextOnConnection; 158 159 // This string extra specifies a network to open the connect dialog on, so the user can enter 160 // network credentials. This is used by quick settings for secured networks, among other 161 // things. 162 private static final String EXTRA_START_CONNECT_SSID = "wifi_start_connect_ssid"; 163 private String mOpenSsid; 164 isVerboseLoggingEnabled()165 private static boolean isVerboseLoggingEnabled() { 166 return WifiPickerTracker.isVerboseLoggingEnabled(); 167 } 168 169 private boolean mIsWifiEntryListStale = true; 170 private final Runnable mUpdateWifiEntryPreferencesRunnable = () -> { 171 updateWifiEntryPreferences(); 172 }; 173 private final Runnable mHideProgressBarRunnable = () -> { 174 setProgressBarVisible(false); 175 }; 176 177 protected WifiManager mWifiManager; 178 private WifiManager.ActionListener mConnectListener; 179 private WifiManager.ActionListener mSaveListener; 180 private WifiManager.ActionListener mForgetListener; 181 182 /** 183 * The state of {@link #isUiRestricted()} at {@link #onCreate(Bundle)}}. This is neccesary to 184 * ensure that behavior is consistent if {@link #isUiRestricted()} changes. It could be changed 185 * by the Test DPC tool in AFW mode. 186 */ 187 private boolean mIsRestricted; 188 189 private WifiEnabler mWifiEnabler; 190 191 // Worker thread used for WifiPickerTracker work 192 private HandlerThread mWorkerThread; 193 194 @VisibleForTesting 195 WifiPickerTracker mWifiPickerTracker; 196 197 private WifiDialog2 mDialog; 198 199 private View mProgressHeader; 200 201 private PreferenceCategory mConnectedWifiEntryPreferenceCategory; 202 private PreferenceCategory mWifiEntryPreferenceCategory; 203 @VisibleForTesting 204 AddWifiNetworkPreference mAddWifiNetworkPreference; 205 @VisibleForTesting 206 Preference mConfigureWifiSettingsPreference; 207 @VisibleForTesting 208 Preference mSavedNetworksPreference; 209 @VisibleForTesting 210 DataUsagePreference mDataUsagePreference; 211 private LinkablePreference mStatusMessagePreference; 212 213 /** 214 * Tracks whether the user initiated a connection via clicking in order to autoscroll to the 215 * network once connected. 216 */ 217 private boolean mClickedConnect; 218 WifiSettings()219 public WifiSettings() { 220 super(DISALLOW_CONFIG_WIFI); 221 } 222 223 @Override onViewCreated(View view, Bundle savedInstanceState)224 public void onViewCreated(View view, Bundle savedInstanceState) { 225 super.onViewCreated(view, savedInstanceState); 226 final Activity activity = getActivity(); 227 if (activity != null) { 228 mProgressHeader = setPinnedHeaderView(R.layout.progress_header) 229 .findViewById(R.id.progress_bar_animation); 230 setProgressBarVisible(false); 231 } 232 ((SettingsActivity) activity).getSwitchBar().setTitle( 233 getContext().getString(R.string.wifi_settings_primary_switch_title)); 234 } 235 236 @Override onCreate(Bundle icicle)237 public void onCreate(Bundle icicle) { 238 super.onCreate(icicle); 239 240 if (IS_ENABLED_PROVIDER_MODEL) { 241 final Intent intent = new Intent("android.settings.NETWORK_PROVIDER_SETTINGS"); 242 // Add FLAG_ACTIVITY_NEW_TASK and FLAG_ACTIVITY_CLEAR_TASK to avoid multiple 243 // instances issue. (e.g. b/191956700) 244 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); 245 final Bundle extras = getActivity().getIntent().getExtras(); 246 if (extras != null) { 247 intent.putExtras(extras); 248 } 249 getContext().startActivity(intent); 250 finish(); 251 return; 252 } 253 254 // TODO(b/37429702): Add animations and preference comparator back after initial screen is 255 // loaded (ODR). 256 setAnimationAllowed(false); 257 258 addPreferences(); 259 260 mIsRestricted = isUiRestricted(); 261 } 262 addPreferences()263 private void addPreferences() { 264 addPreferencesFromResource(R.xml.wifi_settings); 265 266 mConnectedWifiEntryPreferenceCategory = findPreference(PREF_KEY_CONNECTED_ACCESS_POINTS); 267 mWifiEntryPreferenceCategory = findPreference(PREF_KEY_ACCESS_POINTS); 268 mConfigureWifiSettingsPreference = findPreference(PREF_KEY_CONFIGURE_WIFI_SETTINGS); 269 mSavedNetworksPreference = findPreference(PREF_KEY_SAVED_NETWORKS); 270 mAddWifiNetworkPreference = new AddWifiNetworkPreference(getPrefContext()); 271 mStatusMessagePreference = findPreference(PREF_KEY_STATUS_MESSAGE); 272 mDataUsagePreference = findPreference(PREF_KEY_DATA_USAGE); 273 mDataUsagePreference.setVisible(DataUsageUtils.hasWifiRadio(getContext())); 274 mDataUsagePreference.setTemplate( 275 NetworkTemplate.buildTemplateWifi(NetworkTemplate.WIFI_NETWORKID_ALL, 276 null /* subscriberId */), 0 /*subId*/, null /*service*/); 277 } 278 279 @Override onActivityCreated(Bundle savedInstanceState)280 public void onActivityCreated(Bundle savedInstanceState) { 281 super.onActivityCreated(savedInstanceState); 282 283 final Context context = getContext(); 284 mWorkerThread = new HandlerThread(TAG 285 + "{" + Integer.toHexString(System.identityHashCode(this)) + "}", 286 Process.THREAD_PRIORITY_BACKGROUND); 287 mWorkerThread.start(); 288 final Clock elapsedRealtimeClock = new SimpleClock(ZoneOffset.UTC) { 289 @Override 290 public long millis() { 291 return SystemClock.elapsedRealtime(); 292 } 293 }; 294 mWifiPickerTracker = FeatureFactory.getFactory(context) 295 .getWifiTrackerLibProvider() 296 .createWifiPickerTracker(getSettingsLifecycle(), context, 297 new Handler(Looper.getMainLooper()), 298 mWorkerThread.getThreadHandler(), 299 elapsedRealtimeClock, 300 MAX_SCAN_AGE_MILLIS, 301 SCAN_INTERVAL_MILLIS, 302 this); 303 304 final Activity activity = getActivity(); 305 306 if (activity != null) { 307 mWifiManager = getActivity().getSystemService(WifiManager.class); 308 } 309 310 mConnectListener = new WifiConnectListener(getActivity()); 311 312 mSaveListener = new WifiManager.ActionListener() { 313 @Override 314 public void onSuccess() { 315 } 316 317 @Override 318 public void onFailure(int reason) { 319 Activity activity = getActivity(); 320 if (activity != null) { 321 Toast.makeText(activity, 322 R.string.wifi_failed_save_message, 323 Toast.LENGTH_SHORT).show(); 324 } 325 } 326 }; 327 328 mForgetListener = new WifiManager.ActionListener() { 329 @Override 330 public void onSuccess() { 331 } 332 333 @Override 334 public void onFailure(int reason) { 335 Activity activity = getActivity(); 336 if (activity != null) { 337 Toast.makeText(activity, 338 R.string.wifi_failed_forget_message, 339 Toast.LENGTH_SHORT).show(); 340 } 341 } 342 }; 343 registerForContextMenu(getListView()); 344 setHasOptionsMenu(true); 345 346 if (savedInstanceState != null) { 347 mDialogMode = savedInstanceState.getInt(SAVE_DIALOG_MODE); 348 mDialogWifiEntryKey = savedInstanceState.getString(SAVE_DIALOG_WIFIENTRY_KEY); 349 } 350 351 // If we're supposed to enable/disable the Next button based on our current connection 352 // state, start it off in the right state. 353 final Intent intent = getActivity().getIntent(); 354 mEnableNextOnConnection = intent.getBooleanExtra(EXTRA_ENABLE_NEXT_ON_CONNECT, false); 355 356 if (intent.hasExtra(EXTRA_START_CONNECT_SSID)) { 357 mOpenSsid = intent.getStringExtra(EXTRA_START_CONNECT_SSID); 358 } 359 360 // After rebooting the device, the Wi-Fi state will not be called back in the airplane 361 // mode, need to call onWifiStateChanged() to update the initial state of the UI. 362 onWifiStateChanged(); 363 } 364 365 @Override onDestroyView()366 public void onDestroyView() { 367 if (mWifiEnabler != null) { 368 mWifiEnabler.teardownSwitchController(); 369 } 370 mWorkerThread.quit(); 371 372 super.onDestroyView(); 373 } 374 375 @Override onStart()376 public void onStart() { 377 super.onStart(); 378 379 mWifiEnabler = createWifiEnabler(); 380 381 if (mIsRestricted) { 382 restrictUi(); 383 } 384 } 385 restrictUi()386 private void restrictUi() { 387 if (!isUiRestrictedByOnlyAdmin()) { 388 getEmptyTextView().setText(R.string.wifi_empty_list_user_restricted); 389 } 390 getPreferenceScreen().removeAll(); 391 } 392 393 /** 394 * @return new WifiEnabler 395 */ createWifiEnabler()396 private WifiEnabler createWifiEnabler() { 397 final SettingsActivity activity = (SettingsActivity) getActivity(); 398 return new WifiEnabler(activity, new MainSwitchBarController(activity.getSwitchBar()), 399 mMetricsFeatureProvider); 400 } 401 402 @Override onResume()403 public void onResume() { 404 final Activity activity = getActivity(); 405 super.onResume(); 406 407 // Because RestrictedSettingsFragment's onResume potentially requests authorization, 408 // which changes the restriction state, recalculate it. 409 final boolean alreadyImmutablyRestricted = mIsRestricted; 410 mIsRestricted = isUiRestricted(); 411 if (!alreadyImmutablyRestricted && mIsRestricted) { 412 restrictUi(); 413 } 414 415 if (mWifiEnabler != null) { 416 mWifiEnabler.resume(activity); 417 } 418 419 changeNextButtonState(mWifiPickerTracker.getConnectedWifiEntry() != null); 420 } 421 422 @Override onPause()423 public void onPause() { 424 super.onPause(); 425 if (mWifiEnabler != null) { 426 mWifiEnabler.pause(); 427 } 428 } 429 430 @Override onStop()431 public void onStop() { 432 getView().removeCallbacks(mUpdateWifiEntryPreferencesRunnable); 433 getView().removeCallbacks(mHideProgressBarRunnable); 434 mIsWifiEntryListStale = true; 435 super.onStop(); 436 } 437 438 @Override onActivityResult(int requestCode, int resultCode, Intent data)439 public void onActivityResult(int requestCode, int resultCode, Intent data) { 440 super.onActivityResult(requestCode, resultCode, data); 441 442 if (requestCode == ADD_NETWORK_REQUEST) { 443 handleAddNetworkRequest(resultCode, data); 444 return; 445 } else if (requestCode == REQUEST_CODE_WIFI_DPP_ENROLLEE_QR_CODE_SCANNER) { 446 if (resultCode == Activity.RESULT_OK) { 447 if (mDialog != null) { 448 mDialog.dismiss(); 449 } 450 } 451 return; 452 } else if (requestCode == CONFIG_NETWORK_REQUEST) { 453 if (resultCode == Activity.RESULT_OK) { 454 final WifiConfiguration wifiConfiguration = data.getParcelableExtra( 455 ConfigureWifiEntryFragment.NETWORK_CONFIG_KEY); 456 if (wifiConfiguration != null) { 457 mWifiManager.connect(wifiConfiguration, 458 new WifiConnectActionListener()); 459 } 460 } 461 return; 462 } else if (requestCode == MANAGE_SUBSCRIPTION) { 463 //Do nothing 464 return; 465 } 466 467 final boolean formerlyRestricted = mIsRestricted; 468 mIsRestricted = isUiRestricted(); 469 if (formerlyRestricted && !mIsRestricted 470 && getPreferenceScreen().getPreferenceCount() == 0) { 471 // De-restrict the ui 472 addPreferences(); 473 } 474 } 475 476 @Override onCreateAdapter(PreferenceScreen preferenceScreen)477 protected RecyclerView.Adapter onCreateAdapter(PreferenceScreen preferenceScreen) { 478 final RecyclerView.Adapter adapter = super.onCreateAdapter(preferenceScreen); 479 adapter.setHasStableIds(true); 480 return adapter; 481 } 482 483 @Override getMetricsCategory()484 public int getMetricsCategory() { 485 return SettingsEnums.WIFI; 486 } 487 488 @Override onSaveInstanceState(Bundle outState)489 public void onSaveInstanceState(Bundle outState) { 490 super.onSaveInstanceState(outState); 491 // If dialog has been shown, save its state. 492 if (mDialog != null) { 493 outState.putInt(SAVE_DIALOG_MODE, mDialogMode); 494 outState.putString(SAVE_DIALOG_WIFIENTRY_KEY, mDialogWifiEntryKey); 495 } 496 } 497 498 @Override onCreateContextMenu(ContextMenu menu, View view, ContextMenuInfo info)499 public void onCreateContextMenu(ContextMenu menu, View view, ContextMenuInfo info) { 500 Preference preference = (Preference) view.getTag(); 501 if (!(preference instanceof LongPressWifiEntryPreference)) { 502 // Do nothing. 503 return; 504 } 505 506 // Cache the WifiEntry for onContextItemSelected. Don't use it in other methods. 507 mSelectedWifiEntry = ((LongPressWifiEntryPreference) preference).getWifiEntry(); 508 509 menu.setHeaderTitle(mSelectedWifiEntry.getTitle()); 510 if (mSelectedWifiEntry.canConnect()) { 511 menu.add(Menu.NONE, MENU_ID_CONNECT, 0 /* order */, R.string.wifi_connect); 512 } 513 514 if (mSelectedWifiEntry.canDisconnect()) { 515 menu.add(Menu.NONE, MENU_ID_SHARE, 0 /* order */, R.string.share); 516 menu.add(Menu.NONE, MENU_ID_DISCONNECT, 1 /* order */, 517 R.string.wifi_disconnect_button_text); 518 } 519 520 // "forget" for normal saved network. And "disconnect" for ephemeral network because it 521 // could only be disconnected and be put in blocklists so it won't be used again. 522 if (canForgetNetwork()) { 523 menu.add(Menu.NONE, MENU_ID_FORGET, 0 /* order */, R.string.forget); 524 } 525 526 WifiConfiguration config = mSelectedWifiEntry.getWifiConfiguration(); 527 // Some configs are ineditable 528 if (WifiUtils.isNetworkLockedDown(getActivity(), config)) { 529 return; 530 } 531 532 if (mSelectedWifiEntry.isSaved() && mSelectedWifiEntry.getConnectedState() 533 != WifiEntry.CONNECTED_STATE_CONNECTED) { 534 menu.add(Menu.NONE, MENU_ID_MODIFY, 0 /* order */, R.string.wifi_modify); 535 } 536 } 537 canForgetNetwork()538 private boolean canForgetNetwork() { 539 return mSelectedWifiEntry.canForget() && !WifiUtils.isNetworkLockedDown(getActivity(), 540 mSelectedWifiEntry.getWifiConfiguration()); 541 } 542 543 @Override onContextItemSelected(MenuItem item)544 public boolean onContextItemSelected(MenuItem item) { 545 switch (item.getItemId()) { 546 case MENU_ID_CONNECT: 547 connect(mSelectedWifiEntry, true /* editIfNoConfig */, false /* fullScreenEdit */); 548 return true; 549 case MENU_ID_DISCONNECT: 550 mSelectedWifiEntry.disconnect(null /* callback */); 551 return true; 552 case MENU_ID_FORGET: 553 forget(mSelectedWifiEntry); 554 return true; 555 case MENU_ID_SHARE: 556 WifiDppUtils.showLockScreen(getContext(), 557 () -> launchWifiDppConfiguratorActivity(mSelectedWifiEntry)); 558 return true; 559 case MENU_ID_MODIFY: 560 showDialog(mSelectedWifiEntry, WifiConfigUiBase2.MODE_MODIFY); 561 return true; 562 default: 563 return super.onContextItemSelected(item); 564 } 565 } 566 567 @Override onPreferenceTreeClick(Preference preference)568 public boolean onPreferenceTreeClick(Preference preference) { 569 // If the preference has a fragment set, open that 570 if (preference.getFragment() != null) { 571 preference.setOnPreferenceClickListener(null); 572 return super.onPreferenceTreeClick(preference); 573 } 574 575 if (preference instanceof LongPressWifiEntryPreference) { 576 final WifiEntry selectedEntry = 577 ((LongPressWifiEntryPreference) preference).getWifiEntry(); 578 579 if (selectedEntry.shouldEditBeforeConnect()) { 580 launchConfigNewNetworkFragment(selectedEntry); 581 return true; 582 } 583 584 connect(selectedEntry, true /* editIfNoConfig */, true /* fullScreenEdit */); 585 } else if (preference == mAddWifiNetworkPreference) { 586 onAddNetworkPressed(); 587 } else { 588 return super.onPreferenceTreeClick(preference); 589 } 590 return true; 591 } 592 showDialog(WifiEntry wifiEntry, int dialogMode)593 private void showDialog(WifiEntry wifiEntry, int dialogMode) { 594 if (WifiUtils.isNetworkLockedDown(getActivity(), wifiEntry.getWifiConfiguration()) 595 && wifiEntry.getConnectedState() == WifiEntry.CONNECTED_STATE_CONNECTED) { 596 RestrictedLockUtils.sendShowAdminSupportDetailsIntent(getActivity(), 597 RestrictedLockUtilsInternal.getDeviceOwner(getActivity())); 598 return; 599 } 600 601 if (mDialog != null) { 602 removeDialog(WIFI_DIALOG_ID); 603 mDialog = null; 604 } 605 606 // Save the access point and edit mode 607 mDialogWifiEntry = wifiEntry; 608 mDialogWifiEntryKey = wifiEntry.getKey(); 609 mDialogMode = dialogMode; 610 611 showDialog(WIFI_DIALOG_ID); 612 } 613 614 @Override onCreateDialog(int dialogId)615 public Dialog onCreateDialog(int dialogId) { 616 switch (dialogId) { 617 case WIFI_DIALOG_ID: 618 // modify network 619 mDialog = WifiDialog2 620 .createModal(getActivity(), this, mDialogWifiEntry, mDialogMode); 621 return mDialog; 622 default: 623 return super.onCreateDialog(dialogId); 624 } 625 } 626 627 @Override onDialogShowing()628 public void onDialogShowing() { 629 super.onDialogShowing(); 630 setOnDismissListener(this); 631 } 632 633 @Override onDismiss(DialogInterface dialog)634 public void onDismiss(DialogInterface dialog) { 635 // We don't keep any dialog object when dialog was dismissed. 636 mDialog = null; 637 mDialogWifiEntry = null; 638 mDialogWifiEntryKey = null; 639 } 640 641 @Override getDialogMetricsCategory(int dialogId)642 public int getDialogMetricsCategory(int dialogId) { 643 switch (dialogId) { 644 case WIFI_DIALOG_ID: 645 return SettingsEnums.DIALOG_WIFI_AP_EDIT; 646 default: 647 return 0; 648 } 649 } 650 651 /** Called when the state of Wifi has changed. */ 652 @Override onWifiStateChanged()653 public void onWifiStateChanged() { 654 if (mIsRestricted) { 655 return; 656 } 657 final int wifiState = mWifiPickerTracker.getWifiState(); 658 659 if (isVerboseLoggingEnabled()) { 660 Log.i(TAG, "onWifiStateChanged called with wifi state: " + wifiState); 661 } 662 663 switch (wifiState) { 664 case WifiManager.WIFI_STATE_ENABLED: 665 updateWifiEntryPreferences(); 666 break; 667 668 case WifiManager.WIFI_STATE_ENABLING: 669 removeConnectedWifiEntryPreference(); 670 removeWifiEntryPreference(); 671 addMessagePreference(R.string.wifi_starting); 672 setProgressBarVisible(true); 673 break; 674 675 case WifiManager.WIFI_STATE_DISABLING: 676 removeConnectedWifiEntryPreference(); 677 removeWifiEntryPreference(); 678 addMessagePreference(R.string.wifi_stopping); 679 break; 680 681 case WifiManager.WIFI_STATE_DISABLED: 682 setOffMessage(); 683 setAdditionalSettingsSummaries(); 684 setProgressBarVisible(false); 685 mClickedConnect = false; 686 break; 687 } 688 } 689 690 @Override onWifiEntriesChanged()691 public void onWifiEntriesChanged() { 692 if (mIsWifiEntryListStale) { 693 mIsWifiEntryListStale = false; 694 updateWifiEntryPreferences(); 695 } else { 696 updateWifiEntryPreferencesDelayed(); 697 } 698 changeNextButtonState(mWifiPickerTracker.getConnectedWifiEntry() != null); 699 700 // Edit the Wi-Fi network of specified SSID. 701 if (mOpenSsid != null) { 702 Optional<WifiEntry> matchedWifiEntry = mWifiPickerTracker.getWifiEntries().stream() 703 .filter(wifiEntry -> TextUtils.equals(mOpenSsid, wifiEntry.getSsid())) 704 .filter(wifiEntry -> wifiEntry.getSecurity() != WifiEntry.SECURITY_NONE 705 && wifiEntry.getSecurity() != WifiEntry.SECURITY_OWE) 706 .filter(wifiEntry -> !wifiEntry.isSaved() 707 || isDisabledByWrongPassword(wifiEntry)) 708 .findFirst(); 709 if (matchedWifiEntry.isPresent()) { 710 mOpenSsid = null; 711 launchConfigNewNetworkFragment(matchedWifiEntry.get()); 712 } 713 } 714 } 715 716 @Override onNumSavedNetworksChanged()717 public void onNumSavedNetworksChanged() { 718 if (isFinishingOrDestroyed()) { 719 return; 720 } 721 setAdditionalSettingsSummaries(); 722 } 723 724 @Override onNumSavedSubscriptionsChanged()725 public void onNumSavedSubscriptionsChanged() { 726 if (isFinishingOrDestroyed()) { 727 return; 728 } 729 setAdditionalSettingsSummaries(); 730 } 731 732 /** 733 * Updates WifiEntries from {@link WifiPickerTracker#getWifiEntries()}. Adds a delay to have 734 * progress bar displayed before starting to modify entries. 735 */ updateWifiEntryPreferencesDelayed()736 private void updateWifiEntryPreferencesDelayed() { 737 // Safeguard from some delayed event handling 738 if (getActivity() != null && !mIsRestricted 739 && mWifiPickerTracker.getWifiState() == WifiManager.WIFI_STATE_ENABLED) { 740 final View view = getView(); 741 final Handler handler = view.getHandler(); 742 if (handler != null && handler.hasCallbacks(mUpdateWifiEntryPreferencesRunnable)) { 743 return; 744 } 745 setProgressBarVisible(true); 746 view.postDelayed(mUpdateWifiEntryPreferencesRunnable, 300); 747 } 748 } 749 updateWifiEntryPreferences()750 private void updateWifiEntryPreferences() { 751 // in case state has changed 752 if (mWifiPickerTracker.getWifiState() != WifiManager.WIFI_STATE_ENABLED) { 753 return; 754 } 755 756 boolean hasAvailableWifiEntries = false; 757 mStatusMessagePreference.setVisible(false); 758 mWifiEntryPreferenceCategory.setVisible(true); 759 760 final WifiEntry connectedEntry = mWifiPickerTracker.getConnectedWifiEntry(); 761 mConnectedWifiEntryPreferenceCategory.setVisible(connectedEntry != null); 762 if (connectedEntry != null) { 763 final LongPressWifiEntryPreference connectedPref = 764 mConnectedWifiEntryPreferenceCategory.findPreference(connectedEntry.getKey()); 765 if (connectedPref == null || connectedPref.getWifiEntry() != connectedEntry) { 766 mConnectedWifiEntryPreferenceCategory.removeAll(); 767 final ConnectedWifiEntryPreference pref = 768 new ConnectedWifiEntryPreference(getPrefContext(), connectedEntry, this); 769 pref.setKey(connectedEntry.getKey()); 770 pref.refresh(); 771 mConnectedWifiEntryPreferenceCategory.addPreference(pref); 772 pref.setOnPreferenceClickListener(preference -> { 773 if (connectedEntry.canSignIn()) { 774 connectedEntry.signIn(null /* callback */); 775 } else { 776 launchNetworkDetailsFragment(pref); 777 } 778 return true; 779 }); 780 pref.setOnGearClickListener(preference -> { 781 launchNetworkDetailsFragment(pref); 782 }); 783 784 if (mClickedConnect) { 785 mClickedConnect = false; 786 scrollToPreference(mConnectedWifiEntryPreferenceCategory); 787 } 788 } 789 } else { 790 mConnectedWifiEntryPreferenceCategory.removeAll(); 791 } 792 793 int index = 0; 794 cacheRemoveAllPrefs(mWifiEntryPreferenceCategory); 795 List<WifiEntry> wifiEntries = mWifiPickerTracker.getWifiEntries(); 796 for (WifiEntry wifiEntry : wifiEntries) { 797 hasAvailableWifiEntries = true; 798 799 String key = wifiEntry.getKey(); 800 LongPressWifiEntryPreference pref = 801 (LongPressWifiEntryPreference) getCachedPreference(key); 802 if (pref != null) { 803 if (pref.getWifiEntry() == wifiEntry) { 804 pref.setOrder(index++); 805 continue; 806 } else { 807 // Create a new preference if the underlying WifiEntry object has changed 808 removePreference(key); 809 } 810 } 811 812 pref = createLongPressWifiEntryPreference(wifiEntry); 813 pref.setKey(wifiEntry.getKey()); 814 pref.setOrder(index++); 815 pref.refresh(); 816 817 if (wifiEntry.getHelpUriString() != null) { 818 pref.setOnButtonClickListener(preference -> { 819 openSubscriptionHelpPage(wifiEntry); 820 }); 821 } 822 mWifiEntryPreferenceCategory.addPreference(pref); 823 } 824 removeCachedPrefs(mWifiEntryPreferenceCategory); 825 826 if (!hasAvailableWifiEntries) { 827 setProgressBarVisible(true); 828 Preference pref = new Preference(getPrefContext()); 829 pref.setSelectable(false); 830 pref.setSummary(R.string.wifi_empty_list_wifi_on); 831 pref.setOrder(index++); 832 pref.setKey(PREF_KEY_EMPTY_WIFI_LIST); 833 mWifiEntryPreferenceCategory.addPreference(pref); 834 } else { 835 // Continuing showing progress bar for an additional delay to overlap with animation 836 getView().postDelayed(mHideProgressBarRunnable, 1700 /* delay millis */); 837 } 838 839 mAddWifiNetworkPreference.setOrder(index++); 840 mWifiEntryPreferenceCategory.addPreference(mAddWifiNetworkPreference); 841 setAdditionalSettingsSummaries(); 842 } 843 launchNetworkDetailsFragment(LongPressWifiEntryPreference pref)844 private void launchNetworkDetailsFragment(LongPressWifiEntryPreference pref) { 845 final WifiEntry wifiEntry = pref.getWifiEntry(); 846 final Context context = getContext(); 847 final CharSequence title = 848 FeatureFlagUtils.isEnabled(context, FeatureFlags.WIFI_DETAILS_DATAUSAGE_HEADER) 849 ? wifiEntry.getTitle() 850 : context.getText(R.string.pref_title_network_details); 851 852 final Bundle bundle = new Bundle(); 853 bundle.putString(WifiNetworkDetailsFragment.KEY_CHOSEN_WIFIENTRY_KEY, wifiEntry.getKey()); 854 855 new SubSettingLauncher(context) 856 .setTitleText(title) 857 .setDestination(WifiNetworkDetailsFragment.class.getName()) 858 .setArguments(bundle) 859 .setSourceMetricsCategory(getMetricsCategory()) 860 .launch(); 861 } 862 863 @VisibleForTesting createLongPressWifiEntryPreference(WifiEntry wifiEntry)864 LongPressWifiEntryPreference createLongPressWifiEntryPreference(WifiEntry wifiEntry) { 865 return new LongPressWifiEntryPreference(getPrefContext(), wifiEntry, this); 866 } 867 launchAddNetworkFragment()868 private void launchAddNetworkFragment() { 869 new SubSettingLauncher(getContext()) 870 .setTitleRes(R.string.wifi_add_network) 871 .setDestination(AddNetworkFragment.class.getName()) 872 .setSourceMetricsCategory(getMetricsCategory()) 873 .setResultListener(this, ADD_NETWORK_REQUEST) 874 .launch(); 875 } 876 877 /** Removes all preferences and hide the {@link #mConnectedWifiEntryPreferenceCategory}. */ removeConnectedWifiEntryPreference()878 private void removeConnectedWifiEntryPreference() { 879 mConnectedWifiEntryPreferenceCategory.removeAll(); 880 mConnectedWifiEntryPreferenceCategory.setVisible(false); 881 } 882 removeWifiEntryPreference()883 private void removeWifiEntryPreference() { 884 mWifiEntryPreferenceCategory.removeAll(); 885 mWifiEntryPreferenceCategory.setVisible(false); 886 } 887 888 @VisibleForTesting setAdditionalSettingsSummaries()889 void setAdditionalSettingsSummaries() { 890 mConfigureWifiSettingsPreference.setSummary(getString( 891 isWifiWakeupEnabled() 892 ? R.string.wifi_configure_settings_preference_summary_wakeup_on 893 : R.string.wifi_configure_settings_preference_summary_wakeup_off)); 894 895 final int numSavedNetworks = mWifiPickerTracker.getNumSavedNetworks(); 896 final int numSavedSubscriptions = mWifiPickerTracker.getNumSavedSubscriptions(); 897 if (numSavedNetworks + numSavedSubscriptions > 0) { 898 mSavedNetworksPreference.setVisible(true); 899 mSavedNetworksPreference.setSummary( 900 getSavedNetworkSettingsSummaryText(numSavedNetworks, numSavedSubscriptions)); 901 } else { 902 mSavedNetworksPreference.setVisible(false); 903 } 904 } 905 getSavedNetworkSettingsSummaryText( int numSavedNetworks, int numSavedSubscriptions)906 private String getSavedNetworkSettingsSummaryText( 907 int numSavedNetworks, int numSavedSubscriptions) { 908 if (numSavedSubscriptions == 0) { 909 return getResources().getQuantityString(R.plurals.wifi_saved_access_points_summary, 910 numSavedNetworks, numSavedNetworks); 911 } else if (numSavedNetworks == 0) { 912 return getResources().getQuantityString( 913 R.plurals.wifi_saved_passpoint_access_points_summary, 914 numSavedSubscriptions, numSavedSubscriptions); 915 } else { 916 final int numTotalEntries = numSavedNetworks + numSavedSubscriptions; 917 return getResources().getQuantityString(R.plurals.wifi_saved_all_access_points_summary, 918 numTotalEntries, numTotalEntries); 919 } 920 } 921 isWifiWakeupEnabled()922 private boolean isWifiWakeupEnabled() { 923 final Context context = getContext(); 924 final PowerManager powerManager = context.getSystemService(PowerManager.class); 925 final ContentResolver contentResolver = context.getContentResolver(); 926 return mWifiManager.isAutoWakeupEnabled() 927 && mWifiManager.isScanAlwaysAvailable() 928 && Settings.Global.getInt(contentResolver, 929 Settings.Global.AIRPLANE_MODE_ON, 0) == 0 930 && !powerManager.isPowerSaveMode(); 931 } 932 setOffMessage()933 private void setOffMessage() { 934 final CharSequence title = getText(R.string.wifi_empty_list_wifi_off); 935 // Don't use WifiManager.isScanAlwaysAvailable() to check the Wi-Fi scanning mode. Instead, 936 // read the system settings directly. Because when the device is in Airplane mode, even if 937 // Wi-Fi scanning mode is on, WifiManager.isScanAlwaysAvailable() still returns "off". 938 // TODO(b/149421497): Fix this? 939 final boolean wifiScanningMode = mWifiManager.isScanAlwaysAvailable(); 940 final CharSequence description = wifiScanningMode ? getText(R.string.wifi_scan_notify_text) 941 : getText(R.string.wifi_scan_notify_text_scanning_off); 942 final LinkifyUtils.OnClickListener clickListener = 943 () -> new SubSettingLauncher(getContext()) 944 .setDestination(WifiScanningFragment.class.getName()) 945 .setTitleRes(R.string.location_scanning_wifi_always_scanning_title) 946 .setSourceMetricsCategory(getMetricsCategory()) 947 .launch(); 948 mStatusMessagePreference.setText(title, description, clickListener); 949 removeConnectedWifiEntryPreference(); 950 removeWifiEntryPreference(); 951 mStatusMessagePreference.setVisible(true); 952 } 953 addMessagePreference(int messageId)954 private void addMessagePreference(int messageId) { 955 mStatusMessagePreference.setTitle(messageId); 956 mStatusMessagePreference.setVisible(true); 957 958 } 959 setProgressBarVisible(boolean visible)960 protected void setProgressBarVisible(boolean visible) { 961 if (mProgressHeader != null) { 962 mProgressHeader.setVisibility(visible ? View.VISIBLE : View.GONE); 963 } 964 } 965 966 @VisibleForTesting handleAddNetworkRequest(int result, Intent data)967 void handleAddNetworkRequest(int result, Intent data) { 968 if (result == Activity.RESULT_OK) { 969 handleAddNetworkSubmitEvent(data); 970 } 971 } 972 handleAddNetworkSubmitEvent(Intent data)973 private void handleAddNetworkSubmitEvent(Intent data) { 974 final WifiConfiguration wifiConfiguration = data.getParcelableExtra( 975 AddNetworkFragment.WIFI_CONFIG_KEY); 976 if (wifiConfiguration != null) { 977 mWifiManager.save(wifiConfiguration, mSaveListener); 978 } 979 } 980 981 /** 982 * Called when "add network" button is pressed. 983 */ onAddNetworkPressed()984 private void onAddNetworkPressed() { 985 launchAddNetworkFragment(); 986 } 987 988 @Override getHelpResource()989 public int getHelpResource() { 990 return R.string.help_url_wifi; 991 } 992 993 /** 994 * Renames/replaces "Next" button when appropriate. "Next" button usually exists in 995 * Wi-Fi setup screens, not in usual wifi settings screen. 996 * 997 * @param enabled true when the device is connected to a wifi network. 998 */ 999 @VisibleForTesting changeNextButtonState(boolean enabled)1000 void changeNextButtonState(boolean enabled) { 1001 if (mEnableNextOnConnection && hasNextButton()) { 1002 getNextButton().setEnabled(enabled); 1003 } 1004 } 1005 1006 @Override onForget(WifiDialog2 dialog)1007 public void onForget(WifiDialog2 dialog) { 1008 forget(dialog.getWifiEntry()); 1009 } 1010 1011 @Override onSubmit(WifiDialog2 dialog)1012 public void onSubmit(WifiDialog2 dialog) { 1013 final int dialogMode = dialog.getMode(); 1014 final WifiConfiguration config = dialog.getController().getConfig(); 1015 final WifiEntry wifiEntry = dialog.getWifiEntry(); 1016 1017 if (dialogMode == WifiConfigUiBase2.MODE_MODIFY) { 1018 if (config == null) { 1019 Toast.makeText(getContext(), R.string.wifi_failed_save_message, 1020 Toast.LENGTH_SHORT).show(); 1021 } else { 1022 mWifiManager.save(config, mSaveListener); 1023 } 1024 } else if (dialogMode == WifiConfigUiBase2.MODE_CONNECT 1025 || (dialogMode == WifiConfigUiBase2.MODE_VIEW && wifiEntry.canConnect())) { 1026 if (config == null) { 1027 connect(wifiEntry, false /* editIfNoConfig */, 1028 false /* fullScreenEdit*/); 1029 } else { 1030 mWifiManager.connect(config, new WifiConnectActionListener()); 1031 } 1032 } 1033 } 1034 1035 @Override onScan(WifiDialog2 dialog, String ssid)1036 public void onScan(WifiDialog2 dialog, String ssid) { 1037 // Launch QR code scanner to join a network. 1038 startActivityForResult( 1039 WifiDppUtils.getEnrolleeQrCodeScannerIntent(dialog.getContext(), ssid), 1040 REQUEST_CODE_WIFI_DPP_ENROLLEE_QR_CODE_SCANNER); 1041 } 1042 forget(WifiEntry wifiEntry)1043 private void forget(WifiEntry wifiEntry) { 1044 mMetricsFeatureProvider.action(getActivity(), SettingsEnums.ACTION_WIFI_FORGET); 1045 wifiEntry.forget(null /* callback */); 1046 } 1047 1048 @VisibleForTesting connect(WifiEntry wifiEntry, boolean editIfNoConfig, boolean fullScreenEdit)1049 void connect(WifiEntry wifiEntry, boolean editIfNoConfig, boolean fullScreenEdit) { 1050 mMetricsFeatureProvider.action(getActivity(), SettingsEnums.ACTION_WIFI_CONNECT, 1051 wifiEntry.isSaved()); 1052 1053 // If it's an unsaved secure WifiEntry, it will callback 1054 // ConnectCallback#onConnectResult with ConnectCallback#CONNECT_STATUS_FAILURE_NO_CONFIG 1055 wifiEntry.connect(new WifiEntryConnectCallback(wifiEntry, editIfNoConfig, 1056 fullScreenEdit)); 1057 } 1058 1059 private class WifiConnectActionListener implements WifiManager.ActionListener { 1060 @Override onSuccess()1061 public void onSuccess() { 1062 mClickedConnect = true; 1063 } 1064 1065 @Override onFailure(int reason)1066 public void onFailure(int reason) { 1067 if (isFinishingOrDestroyed()) { 1068 return; 1069 } 1070 Toast.makeText(getContext(), R.string.wifi_failed_connect_message, Toast.LENGTH_SHORT) 1071 .show(); 1072 } 1073 } 1074 1075 public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = 1076 new BaseSearchIndexProvider(R.xml.wifi_settings) { 1077 @Override 1078 protected boolean isPageSearchEnabled(Context context) { 1079 return !IS_ENABLED_PROVIDER_MODEL; 1080 } 1081 1082 @Override 1083 public List<String> getNonIndexableKeys(Context context) { 1084 final List<String> keys = super.getNonIndexableKeys(context); 1085 1086 final WifiManager wifiManager = context.getSystemService(WifiManager.class); 1087 if (WifiSavedConfigUtils.getAllConfigsCount(context, wifiManager) == 0) { 1088 keys.add(PREF_KEY_SAVED_NETWORKS); 1089 } 1090 1091 if (!DataUsageUtils.hasWifiRadio(context)) { 1092 keys.add(PREF_KEY_DATA_USAGE); 1093 } 1094 return keys; 1095 } 1096 }; 1097 1098 private class WifiEntryConnectCallback implements ConnectCallback { 1099 final WifiEntry mConnectWifiEntry; 1100 final boolean mEditIfNoConfig; 1101 final boolean mFullScreenEdit; 1102 WifiEntryConnectCallback(WifiEntry connectWifiEntry, boolean editIfNoConfig, boolean fullScreenEdit)1103 WifiEntryConnectCallback(WifiEntry connectWifiEntry, boolean editIfNoConfig, 1104 boolean fullScreenEdit) { 1105 mConnectWifiEntry = connectWifiEntry; 1106 mEditIfNoConfig = editIfNoConfig; 1107 mFullScreenEdit = fullScreenEdit; 1108 } 1109 1110 @Override onConnectResult(@onnectStatus int status)1111 public void onConnectResult(@ConnectStatus int status) { 1112 if (isFinishingOrDestroyed()) { 1113 return; 1114 } 1115 1116 if (status == ConnectCallback.CONNECT_STATUS_SUCCESS) { 1117 mClickedConnect = true; 1118 } else if (status == ConnectCallback.CONNECT_STATUS_FAILURE_NO_CONFIG) { 1119 if (mEditIfNoConfig) { 1120 // Edit an unsaved secure Wi-Fi network. 1121 if (mFullScreenEdit) { 1122 launchConfigNewNetworkFragment(mConnectWifiEntry); 1123 } else { 1124 showDialog(mConnectWifiEntry, WifiConfigUiBase2.MODE_CONNECT); 1125 } 1126 } 1127 } else if (status == CONNECT_STATUS_FAILURE_UNKNOWN) { 1128 Toast.makeText(getContext(), R.string.wifi_failed_connect_message, 1129 Toast.LENGTH_SHORT).show(); 1130 } 1131 } 1132 } 1133 launchConfigNewNetworkFragment(WifiEntry wifiEntry)1134 private void launchConfigNewNetworkFragment(WifiEntry wifiEntry) { 1135 final Bundle bundle = new Bundle(); 1136 bundle.putString(WifiNetworkDetailsFragment.KEY_CHOSEN_WIFIENTRY_KEY, 1137 wifiEntry.getKey()); 1138 new SubSettingLauncher(getContext()) 1139 .setTitleText(wifiEntry.getTitle()) 1140 .setDestination(ConfigureWifiEntryFragment.class.getName()) 1141 .setArguments(bundle) 1142 .setSourceMetricsCategory(getMetricsCategory()) 1143 .setResultListener(WifiSettings.this, CONFIG_NETWORK_REQUEST) 1144 .launch(); 1145 } 1146 launchWifiDppConfiguratorActivity(WifiEntry wifiEntry)1147 private void launchWifiDppConfiguratorActivity(WifiEntry wifiEntry) { 1148 final Intent intent = WifiDppUtils.getConfiguratorQrCodeGeneratorIntentOrNull(getContext(), 1149 mWifiManager, wifiEntry); 1150 1151 if (intent == null) { 1152 Log.e(TAG, "Launch Wi-Fi DPP QR code generator with a wrong Wi-Fi network!"); 1153 } else { 1154 mMetricsFeatureProvider.action(SettingsEnums.PAGE_UNKNOWN, 1155 SettingsEnums.ACTION_SETTINGS_SHARE_WIFI_QR_CODE, 1156 SettingsEnums.SETTINGS_WIFI_DPP_CONFIGURATOR, 1157 /* key */ null, 1158 /* value */ Integer.MIN_VALUE); 1159 1160 startActivity(intent); 1161 } 1162 } 1163 1164 /** Helper method to return whether a WifiEntry is disabled due to a wrong password */ isDisabledByWrongPassword(WifiEntry wifiEntry)1165 private static boolean isDisabledByWrongPassword(WifiEntry wifiEntry) { 1166 WifiConfiguration config = wifiEntry.getWifiConfiguration(); 1167 if (config == null) { 1168 return false; 1169 } 1170 WifiConfiguration.NetworkSelectionStatus networkStatus = 1171 config.getNetworkSelectionStatus(); 1172 if (networkStatus == null 1173 || networkStatus.getNetworkSelectionStatus() == NETWORK_SELECTION_ENABLED) { 1174 return false; 1175 } 1176 int reason = networkStatus.getNetworkSelectionDisableReason(); 1177 return WifiConfiguration.NetworkSelectionStatus.DISABLED_BY_WRONG_PASSWORD == reason; 1178 } 1179 1180 @VisibleForTesting openSubscriptionHelpPage(WifiEntry wifiEntry)1181 void openSubscriptionHelpPage(WifiEntry wifiEntry) { 1182 final Intent intent = getHelpIntent(getContext(), wifiEntry.getHelpUriString()); 1183 if (intent != null) { 1184 try { 1185 startActivityForResult(intent, MANAGE_SUBSCRIPTION); 1186 } catch (ActivityNotFoundException e) { 1187 Log.e(TAG, "Activity was not found for intent, " + intent.toString()); 1188 } 1189 } 1190 } 1191 1192 @VisibleForTesting getHelpIntent(Context context, String helpUrlString)1193 Intent getHelpIntent(Context context, String helpUrlString) { 1194 return HelpUtils.getHelpIntent(context, helpUrlString, context.getClass().getName()); 1195 } 1196 } 1197