Provide connect button in Wi-Fi detail page
User can click connect button to connect this AP at the detail page even the Wi-Fi disabled. Would turn on Wi-Fi if disabled and then connect to this saved network. Bug: 126503889 Test: atest and manual test Change-Id: I313e290474d6623a6c3e84027e81d0d1ebf16919
This commit is contained in:
@@ -41,6 +41,7 @@ import android.net.RouteInfo;
|
||||
import android.net.wifi.WifiConfiguration;
|
||||
import android.net.wifi.WifiInfo;
|
||||
import android.net.wifi.WifiManager;
|
||||
import android.os.CountDownTimer;
|
||||
import android.os.Handler;
|
||||
import android.text.TextUtils;
|
||||
import android.util.FeatureFlagUtils;
|
||||
@@ -84,6 +85,7 @@ import java.net.Inet4Address;
|
||||
import java.net.Inet6Address;
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.time.Duration;
|
||||
import java.util.StringJoiner;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@@ -127,6 +129,19 @@ public class WifiDetailPreferenceController extends AbstractPreferenceController
|
||||
@VisibleForTesting
|
||||
static final String KEY_IPV6_ADDRESSES_PREF = "ipv6_addresses";
|
||||
|
||||
private static final int STATE_NONE = 1;
|
||||
private static final int STATE_ENABLE_WIFI = 2;
|
||||
private static final int STATE_ENABLE_WIFI_FAILED = 3;
|
||||
private static final int STATE_CONNECTING = 4;
|
||||
private static final int STATE_CONNECTED = 5;
|
||||
private static final int STATE_FAILED = 6;
|
||||
private static final int STATE_NOT_IN_RANGE = 7;
|
||||
private static final int STATE_DISCONNECTED = 8;
|
||||
private static final long TIMEOUT = Duration.ofSeconds(10).toMillis();
|
||||
|
||||
// Be static to avoid too much object not be reset.
|
||||
private static CountDownTimer mTimer;
|
||||
|
||||
private AccessPoint mAccessPoint;
|
||||
private final ConnectivityManager mConnectivityManager;
|
||||
private final Fragment mFragment;
|
||||
@@ -143,6 +158,9 @@ public class WifiDetailPreferenceController extends AbstractPreferenceController
|
||||
private final WifiTracker mWifiTracker;
|
||||
private final MetricsFeatureProvider mMetricsFeatureProvider;
|
||||
private boolean mIsOutOfRange;
|
||||
private boolean mConnected;
|
||||
private int mConnectingState;
|
||||
private WifiManager.ActionListener mConnectListener;
|
||||
|
||||
// UI elements - in order of appearance
|
||||
private ActionButtonsPreference mButtonsPref;
|
||||
@@ -182,7 +200,7 @@ public class WifiDetailPreferenceController extends AbstractPreferenceController
|
||||
// fall through
|
||||
case WifiManager.NETWORK_STATE_CHANGED_ACTION:
|
||||
case WifiManager.RSSI_CHANGED_ACTION:
|
||||
updateNetworkInfo();
|
||||
refreshPage();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -197,7 +215,7 @@ public class WifiDetailPreferenceController extends AbstractPreferenceController
|
||||
public void onLinkPropertiesChanged(Network network, LinkProperties lp) {
|
||||
if (network.equals(mNetwork) && !lp.equals(mLinkProperties)) {
|
||||
mLinkProperties = lp;
|
||||
updateIpLayerInfo();
|
||||
refreshIpLayerInfo();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -224,12 +242,17 @@ public class WifiDetailPreferenceController extends AbstractPreferenceController
|
||||
}
|
||||
mNetworkCapabilities = nc;
|
||||
refreshButtons();
|
||||
updateIpLayerInfo();
|
||||
refreshIpLayerInfo();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLost(Network network) {
|
||||
// If support detail page for saved network, should update as disconnect but not exit.
|
||||
if (SavedAccessPointsWifiSettings.usingDetailsFragment(mContext)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (network.equals(mNetwork)) {
|
||||
exitActivity();
|
||||
}
|
||||
@@ -240,13 +263,23 @@ public class WifiDetailPreferenceController extends AbstractPreferenceController
|
||||
/** Called when the state of Wifi has changed. */
|
||||
public void onWifiStateChanged(int state) {
|
||||
Log.d(TAG, "onWifiStateChanged(" + state + ")");
|
||||
// Do nothing.
|
||||
if (mConnectingState == STATE_ENABLE_WIFI && state == WifiManager.WIFI_STATE_ENABLED) {
|
||||
updateConnectingState(STATE_CONNECTING);
|
||||
}
|
||||
}
|
||||
|
||||
/** Called when the connection state of wifi has changed. */
|
||||
public void onConnectedChanged() {
|
||||
Log.d(TAG, "onConnectedChanged");
|
||||
// Do nothing.
|
||||
updateAccessPointFromScannedList();
|
||||
if (mConnected != mAccessPoint.isActive()) {
|
||||
Log.d(TAG, "Connection state changed!");
|
||||
mConnected = mAccessPoint.isActive();
|
||||
if (mAccessPoint.isActive()) {
|
||||
updateConnectingState(STATE_CONNECTED);
|
||||
} else {
|
||||
updateConnectingState(STATE_DISCONNECTED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -254,8 +287,7 @@ public class WifiDetailPreferenceController extends AbstractPreferenceController
|
||||
* {@link WifiTracker#getAccessPoints()} should be called to get the updated list.
|
||||
*/
|
||||
public void onAccessPointsChanged() {
|
||||
Log.d(TAG, "onAccessPointsChanged");
|
||||
updateNetworkInfo();
|
||||
refreshPage();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -314,6 +346,19 @@ public class WifiDetailPreferenceController extends AbstractPreferenceController
|
||||
} else {
|
||||
mWifiTracker = null;
|
||||
}
|
||||
mConnected = mAccessPoint.isActive();
|
||||
mConnectingState = STATE_NONE;
|
||||
mConnectListener = new WifiManager.ActionListener() {
|
||||
@Override
|
||||
public void onSuccess() {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(int reason) {
|
||||
updateConnectingState(STATE_FAILED);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -339,10 +384,14 @@ public class WifiDetailPreferenceController extends AbstractPreferenceController
|
||||
.setButton1OnClickListener(view -> forgetNetwork())
|
||||
.setButton2Text(R.string.wifi_sign_in_button_text)
|
||||
.setButton2OnClickListener(view -> signIntoNetwork())
|
||||
.setButton3Text(R.string.share)
|
||||
.setButton3Icon(R.drawable.ic_qrcode_24dp)
|
||||
.setButton3OnClickListener(view -> shareNetwork())
|
||||
.setButton3Visible(WifiDppUtils.isSupportConfiguratorQrCodeGenerator(mAccessPoint));
|
||||
.setButton3Text(R.string.wifi_connect)
|
||||
.setButton3Icon(R.drawable.ic_settings_wireless)
|
||||
.setButton3OnClickListener(view -> connectNetwork())
|
||||
.setButton3Enabled(true)
|
||||
.setButton4Text(R.string.share)
|
||||
.setButton4Icon(R.drawable.ic_qrcode_24dp)
|
||||
.setButton4OnClickListener(view -> shareNetwork())
|
||||
.setButton4Visible(WifiDppUtils.isSupportConfiguratorQrCodeGenerator(mAccessPoint));
|
||||
|
||||
mSignalStrengthPref = screen.findPreference(KEY_SIGNAL_STRENGTH_PREF);
|
||||
mTxLinkSpeedPref = screen.findPreference(KEY_TX_LINK_SPEED);
|
||||
@@ -397,14 +446,18 @@ public class WifiDetailPreferenceController extends AbstractPreferenceController
|
||||
}
|
||||
}
|
||||
|
||||
private void updateNetworkInfo() {
|
||||
mNetwork = mWifiManager.getCurrentNetwork();
|
||||
mLinkProperties = mConnectivityManager.getLinkProperties(mNetwork);
|
||||
mNetworkCapabilities = mConnectivityManager.getNetworkCapabilities(mNetwork);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
// Ensure mNetwork is set before any callbacks above are delivered, since our
|
||||
// NetworkCallback only looks at changes to mNetwork.
|
||||
mNetwork = mWifiManager.getCurrentNetwork();
|
||||
mLinkProperties = mConnectivityManager.getLinkProperties(mNetwork);
|
||||
mNetworkCapabilities = mConnectivityManager.getNetworkCapabilities(mNetwork);
|
||||
updateNetworkInfo();
|
||||
refreshPage();
|
||||
mContext.registerReceiver(mReceiver, mFilter);
|
||||
mConnectivityManager.registerNetworkCallback(mNetworkRequest, mNetworkCallback,
|
||||
mHandler);
|
||||
@@ -421,11 +474,13 @@ public class WifiDetailPreferenceController extends AbstractPreferenceController
|
||||
mConnectivityManager.unregisterNetworkCallback(mNetworkCallback);
|
||||
}
|
||||
|
||||
private void updateNetworkInfo() {
|
||||
private void refreshPage() {
|
||||
if(!updateAccessPoint()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Log.d(TAG, "Update UI!");
|
||||
|
||||
// refresh header
|
||||
refreshEntityHeader();
|
||||
|
||||
@@ -441,26 +496,37 @@ public class WifiDetailPreferenceController extends AbstractPreferenceController
|
||||
// Receive Link Speed Pref
|
||||
refreshRxSpeed();
|
||||
// IP related information
|
||||
updateIpLayerInfo();
|
||||
refreshIpLayerInfo();
|
||||
// MAC Address Pref
|
||||
refreshMacAddress();
|
||||
|
||||
}
|
||||
|
||||
private boolean updateAccessPoint() {
|
||||
boolean changed = false;
|
||||
if (mWifiTracker != null) {
|
||||
// remember mIsOutOfRange as old before updated
|
||||
boolean oldState = mIsOutOfRange;
|
||||
updateAccessPointFromScannedList();
|
||||
// refresh UI if signal level changed for disconnect network.
|
||||
changed = mRssiSignalLevel != mAccessPoint.getLevel();
|
||||
changed |= oldState != mIsOutOfRange;
|
||||
}
|
||||
|
||||
if (mAccessPoint.isActive()) {
|
||||
// No need to fetch LinkProperties and NetworkCapabilities, they are updated by the
|
||||
// callbacks. mNetwork doesn't change except in onResume.
|
||||
// Sometimes {@link WifiManager#getCurrentNetwork()} return null after connected,
|
||||
// refresh it if needed.
|
||||
if (mNetwork == null) {
|
||||
updateNetworkInfo();
|
||||
}
|
||||
mNetworkInfo = mConnectivityManager.getNetworkInfo(mNetwork);
|
||||
mWifiInfo = mWifiManager.getConnectionInfo();
|
||||
if (mNetwork == null || mNetworkInfo == null || mWifiInfo == null) {
|
||||
// Once connected, can't get mNetworkInfo immediately, return false and wait for
|
||||
// next time to update UI.
|
||||
if (SavedAccessPointsWifiSettings.usingDetailsFragment(mContext)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
exitActivity();
|
||||
return false;
|
||||
}
|
||||
@@ -474,6 +540,8 @@ public class WifiDetailPreferenceController extends AbstractPreferenceController
|
||||
}
|
||||
|
||||
private void updateAccessPointFromScannedList() {
|
||||
if (mWifiTracker == null) return;
|
||||
|
||||
mIsOutOfRange = true;
|
||||
|
||||
if (mAccessPoint.getConfig() == null) {
|
||||
@@ -484,7 +552,7 @@ public class WifiDetailPreferenceController extends AbstractPreferenceController
|
||||
if (ap.getConfig() != null
|
||||
&& mAccessPoint.matches(ap.getConfig())) {
|
||||
mAccessPoint = ap;
|
||||
mIsOutOfRange = false;
|
||||
mIsOutOfRange = !mAccessPoint.isReachable();
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -543,6 +611,11 @@ public class WifiDetailPreferenceController extends AbstractPreferenceController
|
||||
band = mContext.getResources().getString(R.string.wifi_band_5ghz);
|
||||
} else {
|
||||
Log.e(TAG, "Unexpected frequency " + frequency);
|
||||
// Connecting state is unstable, make it disappeared if unexpected
|
||||
if (mConnectingState == STATE_CONNECTING) {
|
||||
mFrequencyPref.setVisible(false);
|
||||
}
|
||||
return;
|
||||
}
|
||||
mFrequencyPref.setSummary(band);
|
||||
mFrequencyPref.setVisible(true);
|
||||
@@ -616,12 +689,21 @@ public class WifiDetailPreferenceController extends AbstractPreferenceController
|
||||
private void refreshButtons() {
|
||||
mButtonsPref.setButton1Visible(canForgetNetwork());
|
||||
mButtonsPref.setButton2Visible(canSignIntoNetwork());
|
||||
mButtonsPref.setButton3Visible(canShareNetwork());
|
||||
mButtonsPref.setVisible(
|
||||
canSignIntoNetwork() || canForgetNetwork() || canShareNetwork());
|
||||
mButtonsPref.setButton3Visible(canConnectNetwork());
|
||||
mButtonsPref.setButton4Visible(canShareNetwork());
|
||||
mButtonsPref.setVisible(canSignIntoNetwork()
|
||||
|| canForgetNetwork()
|
||||
|| canShareNetwork()
|
||||
|| canConnectNetwork());
|
||||
}
|
||||
|
||||
private void updateIpLayerInfo() {
|
||||
private boolean canConnectNetwork() {
|
||||
// Display connect button for disconnected AP even not in the range.
|
||||
return SavedAccessPointsWifiSettings.usingDetailsFragment(mContext)
|
||||
&& !mAccessPoint.isActive();
|
||||
}
|
||||
|
||||
private void refreshIpLayerInfo() {
|
||||
// Hide IP layer info if not a connected network.
|
||||
if (!mAccessPoint.isActive() || mNetwork == null || mLinkProperties == null) {
|
||||
mIpAddressPref.setVisible(false);
|
||||
@@ -823,4 +905,169 @@ public class WifiDetailPreferenceController extends AbstractPreferenceController
|
||||
private boolean usingDataUsageHeader(Context context) {
|
||||
return FeatureFlagUtils.isEnabled(context, FeatureFlags.WIFI_DETAILS_DATAUSAGE_HEADER);
|
||||
}
|
||||
|
||||
private void connectNetwork() {
|
||||
final Activity activity = mFragment.getActivity();
|
||||
// error handling, connected/saved network should have mWifiConfig.
|
||||
if (mWifiConfig == null) {
|
||||
Toast.makeText(activity,
|
||||
R.string.wifi_failed_connect_message,
|
||||
Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
|
||||
// init state before connect
|
||||
mConnectingState = STATE_NONE;
|
||||
|
||||
if (mWifiManager.isWifiEnabled()) {
|
||||
updateConnectingState(STATE_CONNECTING);
|
||||
} else {
|
||||
// Enable Wi-Fi automatically to connect AP
|
||||
updateConnectingState(STATE_ENABLE_WIFI);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateConnectingState(int state) {
|
||||
final Activity activity = mFragment.getActivity();
|
||||
Log.d(TAG, "updateConnectingState from " + mConnectingState + " to " + state);
|
||||
switch (mConnectingState) {
|
||||
case STATE_NONE:
|
||||
case STATE_ENABLE_WIFI:
|
||||
if (state == STATE_ENABLE_WIFI) {
|
||||
Log.d(TAG, "Turn on Wi-Fi automatically!");
|
||||
updateConnectedButton(STATE_ENABLE_WIFI);
|
||||
Toast.makeText(activity,
|
||||
R.string.wifi_turned_on_message,
|
||||
Toast.LENGTH_SHORT).show();
|
||||
mWifiManager.setWifiEnabled(true);
|
||||
// start timer for error handling
|
||||
startTimer();
|
||||
} else if (state == STATE_CONNECTING) {
|
||||
Log.d(TAG, "connecting...");
|
||||
updateConnectedButton(STATE_CONNECTING);
|
||||
mWifiManager.connect(mWifiConfig.networkId, mConnectListener);
|
||||
// start timer for error handling since framework didn't call back if failed
|
||||
startTimer();
|
||||
} else if (state == STATE_ENABLE_WIFI_FAILED) {
|
||||
Log.e(TAG, "Wi-Fi failed to enable network!");
|
||||
stopTimer();
|
||||
// reset state
|
||||
state = STATE_NONE;
|
||||
Toast.makeText(activity,
|
||||
R.string.wifi_failed_connect_message,
|
||||
Toast.LENGTH_SHORT).show();
|
||||
updateConnectedButton(STATE_ENABLE_WIFI_FAILED);
|
||||
}
|
||||
// Do not break here for disconnected event.
|
||||
case STATE_CONNECTED:
|
||||
if (state == STATE_DISCONNECTED) {
|
||||
Log.d(TAG, "disconnected");
|
||||
// reset state
|
||||
state = STATE_NONE;
|
||||
updateConnectedButton(STATE_DISCONNECTED);
|
||||
refreshPage();
|
||||
// clear for getting MAC Address from saved configuration
|
||||
mWifiInfo = null;
|
||||
}
|
||||
break;
|
||||
case STATE_CONNECTING:
|
||||
if (state == STATE_CONNECTED) {
|
||||
Log.d(TAG, "connected");
|
||||
stopTimer();
|
||||
updateConnectedButton(STATE_CONNECTED);
|
||||
Toast.makeText(activity,
|
||||
mContext.getString(R.string.wifi_connected_to_message,
|
||||
mAccessPoint.getTitle()),
|
||||
Toast.LENGTH_SHORT).show();
|
||||
|
||||
updateNetworkInfo();
|
||||
refreshPage();
|
||||
} else if (state == STATE_NOT_IN_RANGE) {
|
||||
Log.d(TAG, "AP not in range");
|
||||
stopTimer();
|
||||
// reset state
|
||||
state = STATE_NONE;
|
||||
Toast.makeText(activity,
|
||||
R.string.wifi_not_in_range_message,
|
||||
Toast.LENGTH_SHORT).show();
|
||||
updateConnectedButton(STATE_NOT_IN_RANGE);
|
||||
} else if (state == STATE_FAILED) {
|
||||
Log.d(TAG, "failed");
|
||||
stopTimer();
|
||||
// reset state
|
||||
state = STATE_NONE;
|
||||
Toast.makeText(activity,
|
||||
R.string.wifi_failed_connect_message,
|
||||
Toast.LENGTH_SHORT).show();
|
||||
updateConnectedButton(STATE_FAILED);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
Log.e(TAG, "Invalid state : " + mConnectingState);
|
||||
// don't update invalid state
|
||||
return;
|
||||
}
|
||||
|
||||
mConnectingState = state;
|
||||
}
|
||||
|
||||
private void updateConnectedButton(int state) {
|
||||
switch (state) {
|
||||
case STATE_ENABLE_WIFI:
|
||||
case STATE_CONNECTING:
|
||||
mButtonsPref.setButton3Text(R.string.wifi_connecting)
|
||||
.setButton3Enabled(false);
|
||||
break;
|
||||
case STATE_CONNECTED:
|
||||
mButtonsPref.setButton3Visible(false);
|
||||
break;
|
||||
case STATE_DISCONNECTED:
|
||||
case STATE_NOT_IN_RANGE:
|
||||
case STATE_FAILED:
|
||||
case STATE_ENABLE_WIFI_FAILED:
|
||||
mButtonsPref.setButton3Text(R.string.wifi_connect)
|
||||
.setButton3Icon(R.drawable.ic_settings_wireless)
|
||||
.setButton3Enabled(true)
|
||||
.setButton3Visible(true);
|
||||
break;
|
||||
default:
|
||||
Log.e(TAG, "Invalid connect button state : " + state);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void startTimer() {
|
||||
if (mTimer != null) {
|
||||
stopTimer();
|
||||
}
|
||||
|
||||
mTimer = new CountDownTimer(TIMEOUT, TIMEOUT + 1) {
|
||||
@Override
|
||||
public void onTick(long millisUntilFinished) {
|
||||
// Do nothing
|
||||
}
|
||||
@Override
|
||||
public void onFinish() {
|
||||
Log.e(TAG, "Timeout for state:" + mConnectingState);
|
||||
if (mConnectingState == STATE_ENABLE_WIFI) {
|
||||
updateConnectingState(STATE_ENABLE_WIFI_FAILED);
|
||||
} else if (mConnectingState == STATE_CONNECTING) {
|
||||
updateAccessPointFromScannedList();
|
||||
if (mIsOutOfRange) {
|
||||
updateConnectingState(STATE_NOT_IN_RANGE);
|
||||
} else {
|
||||
updateConnectingState(STATE_FAILED);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
mTimer.start();
|
||||
}
|
||||
|
||||
private void stopTimer() {
|
||||
if (mTimer == null) return;
|
||||
|
||||
mTimer.cancel();
|
||||
mTimer = null;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user